Domanda

Se ho un oggetto come questo:

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

Posso creare un contenitore multi-index per questo in questo modo:

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;

Ma se ho una lezione come questa:

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

Come posso costruire un indice su .bar (). property () per un contenitore di oggetti Foo ?

Normalmente anniderei le chiamate a boost :: bind , ma non riesco a capire come farlo funzionare nel contesto di un contenitore multiindice.

È stato utile?

Soluzione

Credo che sia necessario creare un oggetto predicato che accetta due istanze di Foo e il suo operatore () può chiamare Foo :: bar () su entrambe le istanze.

Qualcosa di simile

struct MyPredicate
{

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

e quindi utilizzare

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

Scopri Riferimento indici MultiIndex ordinati

Altri suggerimenti

Invece di fornire un comparatore definito dall'utente, puoi scrivere un key extractor definito dall'utente:

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;

Vedi Funzioni avanzate degli estrattori di chiavi Boost.MultiIndex

Per quanto mi piace usare lambda per fare cose semplici, questo può degenerare rapidamente :)

Nel tuo caso, dato che è un po 'più complicato, farei affidamento su una funzione gratuita o un comparatore di predicati.

Il predicato ha il vantaggio di definire i tipi in modo più chiaro, quindi di solito è più facile introdurlo.

Inoltre, per motivi di leggibilità, di solito scrivo i miei indici, che danno:

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'approccio predicato richiede più codice boilerplate, ma consente di separare bene la logica di confronto dalla definizione dell'indice, che è essa stessa separata dalla definizione del contenitore.

Una chiara separazione semplifica la visualizzazione della struttura a colpo d'occhio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top