Увеличить многоиндексный контейнер с индексом, основанным на вложенных значениях

StackOverflow https://stackoverflow.com/questions/1628321

  •  06-07-2019
  •  | 
  •  

Вопрос

Если у меня есть такой объект:

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

Я могу создать многоиндексный контейнер для него следующим образом:

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;

Но если у меня есть такой класс:

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

Как создать индекс для .bar (). property () для контейнера объектов Foo ?

Обычно я вкладывал бы вызовы в boost :: bind , но не могу понять, как заставить его работать в контексте многоиндексного контейнера.

Это было полезно?

Решение

Я считаю, что вам нужно создать объект-предикат, который принимает два экземпляра Foo, и его оператор () может вызывать Foo :: bar () в обоих случаях.

Что-то вроде

struct MyPredicate
{

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

, а затем используйте

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

Ознакомьтесь с справкой по заказанным индексам MultiIndex

Другие советы

Насколько мне нравится использовать лямбды для простых вещей, это может быстро выродиться:)

В вашем случае, поскольку это немного сложнее, я бы полагался либо на свободную функцию, либо на предикатный компаратор.

Преимущество предиката состоит в более четком определении типов, поэтому обычно его проще ввести.

Кроме того, для удобства чтения я обычно печатаю свои индексы, что дает:

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;

Подход с использованием предикатов требует большего количества стандартного кода, но он позволяет красиво отделить логику сравнения от определения индекса, которое само по себе отделено от определения контейнера.

Четкое разделение облегчает обзор структуры.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top