Question

Si j'ai un objet comme celui-ci:

struct Bar {
    std::string const& property();
};

Je peux créer un conteneur multi-index comme celui-ci:

struct tag_prop {};
typedef boost::multi_index_container<
    Bar,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<tag_prop>,
            boost::multi_index::const_mem_fun<
                Bar, const std::string&, &Bar::property
            >
        >
    >
    , ... other indexes
> BarContainer;

Mais si j'ai un cours comme celui-ci:

struct Foo {
   Bar const& bar();
};

Comment puis-je construire un index sur .bar (). property () pour un conteneur d'objets Foo ?

Normalement, je nidifierais les appels à boost :: bind , mais je ne vois pas comment le faire fonctionner dans le contexte d'un conteneur à index multiples.

Était-ce utile?

La solution

Je pense que vous devez créer un objet de prédicat prenant deux instances de Foo. Son opérateur () peut appeler Foo :: bar () dans les deux instances.

Quelque chose comme

struct MyPredicate
{

    bool operator() (const Foo& obj1, const Foo& obj2) const
    {
        // fill in here
    }
};

puis utilisez

...
boost::multi_index::ordered_unique<boost::multi_index::tag<tag_prop>, 
    boost::multi_index::identity<Foo>, MyPredicate>,
...

Découvrez Référence sur les index multi-indexés

Autres conseils

Plutôt que de fournir un comparateur défini par l'utilisateur, vous pouvez écrire un extracteur de clé défini par l'utilisateur :

struct FooBarPropertyExtractor
{
  typedef std::string result_type;
  const result_type& oeprator()(const Foo& f)
  {
    return f.bar().property();
  }
};

...

typedef boost::multi_index_container<
        Bar,
        boost::multi_index::indexed_by<
                boost::multi_index::ordered_non_unique<
                        boost::multi_index::tag<tag_prop>,
                        FooBarPropertyExtractor
                >
        >
        , ... other indexes
> FooContainer;

Voir Fonctionnalités avancées des extracteurs de clé Boost.MultiIndex

Même si j'aime utiliser des lambdas pour faire des choses simples, cela peut rapidement dégénérer:)

Dans votre cas, comme c'est un peu plus compliqué, je me baserais soit sur une fonction libre, soit sur un comparateur de prédicats.

Le prédicat présente l'avantage de définir les types plus clairement, il est donc généralement plus facile de l'introduire.

De plus, pour des raisons de lisibilité, je tape généralement mes index, ce qui donne:

namespace mi = boost::multi_index;

struct FooComparator
{
  bool operator()(Foo const& lhs, Foo const& rhs) const
  {
    return lhs.bar().property() < rhs.bar().property();
  }
};

typedef mi::ordered_unique <
          mi::tag<tag_prop>,
          mi::identity<Foo>,
          FooComparator
        > foo_bar_index_t;

typedef boost::multi_index_container <
          Foo,
          mi::indexed_by < 
            foo_bar_index_t,
            // ... other indexes
          >
        > foo_container_t;

L’approche par prédicat nécessite davantage de code standard, mais elle permet de bien séparer la logique de comparaison de la définition d’index, elle-même séparée de la définition du conteneur.

Une séparation claire facilite la visualisation de la structure en un coup d'œil.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top