Pergunta

Se eu tiver um objeto como este:

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

Eu posso criar um recipiente multi-índice para ele assim:

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;

Mas se eu tiver uma classe como este:

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

Como posso construir um índice em .bar().property() para um recipiente de objetos Foo?

chamadas ninho Normalmente gostaria de boost::bind, mas eu não posso descobrir como fazê-lo funcionar no contexto de um recipiente multi-índice.

Foi útil?

Solução

Eu acredito que você precisa para criar um objeto predicado que leva duas instâncias de Foo e seu operador () pode chamar Foo :: bar () em ambos os casos.

Algo como

struct MyPredicate
{

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

e, em seguida, usar

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

Confira MultiIndex referência índices ordenados

Outras dicas

Em vez de fornecer um comparador definido pelo usuário, você pode escrever uma definida pelo usuário extractor chave :

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;

Avançado de chave extratores Boost.MultiIndex

Por mais que eu gosto de usar lambdas para fazer coisas simples, isso pode rapidamente degenerar:)

No seu caso, já que é um pouco mais complicado, eu iria contar quer por uma função livre ou um comparador predicado.

O predicado tem a vantagem de definir tipos mais claramente por isso é geralmente mais fácil de realmente trazê-lo.

Além disso, por causa da legibilidade, eu geralmente typedef meus índices, o que dá:

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;

A abordagem predicado requer mais código padrão, mas permite separar muito bem a lógica de comparação do índice de definição, que é ele próprio separado da definição recipiente.

Separação clara torna mais fácil para ver a estrutura de relance.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top