Pregunta

Si tengo un objeto como este:

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

Puedo crear un contenedor de múltiples índices para esto así:

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;

Pero si tengo una clase como esta:

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

¿Cómo puedo construir un índice en .bar (). property () para un contenedor de objetos Foo ?

Normalmente anidaría las llamadas a boost :: bind , pero no puedo encontrar la manera de hacerlo funcionar en el contexto de un contenedor de índice múltiple.

¿Fue útil?

Solución

Creo que necesita crear un objeto predicado que tome dos instancias de Foo y su operador () puede llamar a Foo :: bar () en ambas instancias.

Algo así

struct MyPredicate
{

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

y luego use

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

Consulte referencia de índices ordenados de MultiIndex

Otros consejos

En lugar de proporcionar un comparador definido por el usuario, puede escribir un extractor de claves definido por el usuario :

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;

Consulte Funciones avanzadas de los extractores de claves Boost.MultiIndex

Por mucho que me guste usar lambdas para hacer cosas simples, esto puede degenerar rápidamente :)

En su caso, dado que es un poco más complicado, confiaría en una función libre o en un comparador de predicados.

El predicado tiene la ventaja de definir tipos más claramente, por lo que generalmente es más fácil incorporarlo.

Además, en aras de la legibilidad, generalmente escribo def de mis índices, lo que da:

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;

El enfoque de predicado requiere más código repetitivo, pero permite separar muy bien la lógica de comparación de la definición del índice, que está separada de la definición del contenedor.

La separación clara hace que sea más fácil ver la estructura de un vistazo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top