boost.multi_index: перебирать индекс в обратном порядке

Мне интересно, можем ли мы перебирать контейнер Boost.Multi_Index в обратном порядке, аналогично вектору STL rbegin() и rend().

Приведенный ниже код в основном заимствован из здесь. При переборе leg_index (последние несколько строк) и выводе имен животных имена животных отображаются в порядке возрастания в зависимости от количества ног. Мне нужно сделать то же самое в порядке убывания.

Любая идея, как это сделать?

Благодарю вас!

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/member.hpp>
#include <string>
#include <iostream>

using namespace boost::multi_index;

struct animal
{
  std::string name;
  int legs;
};

typedef multi_index_container<
  animal,
  indexed_by<
    sequenced<>,
    ordered_non_unique<
      member<
        animal, int, &animal::legs
      >
    >,
    random_access<>
  >
> animal_multi;

int main()
{
  animal_multi animals;

  animals.insert({"cat", 4});
  animals.insert({"shark", 0});
  animals.insert({"spider", 8});

  auto &legs_index = animals.get<1>();
  auto it = legs_index.begin();
  auto end = legs_index.end();
  for (; it != end; ++it)
    std::cout << it->name << '\n';
}

person hebbo    schedule 01.09.2015    source источник
comment
Вы пробовали rbegin() и rend()?   -  person Tanner Sansbury    schedule 01.09.2015
comment
привет @TannerSansbury. Да, я пытался. Я получил ошибку компиляции.   -  person hebbo    schedule 01.09.2015
comment
И компилируется ли размещенный выше код?   -  person Tanner Sansbury    schedule 01.09.2015
comment
Что бы это ни стоило, rbegin() и rend() предоставляются и функционируют должным образом. Ошибки компиляции, вероятно, связаны с тем, что insert() ожидает два аргумента (позиция и элемент); рассмотрите возможность использования push_back() вместо этого. (демонстрация)   -  person Tanner Sansbury    schedule 01.09.2015
comment
Я заменил вставку на push_back и использовал rbegin() и rend(). Не сработало. У меня все еще есть ошибка компиляции.   -  person hebbo    schedule 01.09.2015
comment
Можно ли размножаться на coliru? Работает ли код в связанной демонстрации? Расширение вопроса с ошибками компиляции может помочь тем, кто не может его воспроизвести.   -  person Tanner Sansbury    schedule 01.09.2015
comment
@TannerSansbury, похоже, существуют эти функции или нет, зависит от метода индексации для конкретного индекса. Если я выберу ordered_non_unique в сочетании с sequenced, я получу другой интерфейс для индекса, чем тот, который я получил бы, если бы я выбрал hashed_unique или hashed_non_unique.   -  person hebbo    schedule 02.09.2015


Ответы (1)


Проблема заключается в вызовах вставки:

animals.insert(animals.end(), animal_multi::value_type {"cat", 4});
animals.insert(animals.end(), animal_multi::value_type {"shark", 0});
animals.insert(animals.end(), animal_multi::value_type {"spider", 8});

Теперь просто используйте обратные итераторы:

auto &legs_index = animals.get<1>();
auto it = legs_index.rbegin();
auto end = legs_index.rend();
for (; it != end; ++it)
  std::cout << it->name << '\n';

Жить на Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/member.hpp>
#include <string>
#include <iostream>

using namespace boost::multi_index;

struct animal
{
  std::string name;
  int legs;
};

typedef multi_index_container<
  animal,
  indexed_by<
    sequenced<>,
    ordered_non_unique<
      member<
        animal, int, &animal::legs
      >
    >,
    random_access<>
  >
> animal_multi;

int main()
{
  animal_multi animals;

  animals.insert(animals.end(), animal_multi::value_type {"cat", 4});
  animals.insert(animals.end(), animal_multi::value_type {"shark", 0});
  animals.insert(animals.end(), animal_multi::value_type {"spider", 8});

  auto &legs_index = animals.get<1>();
  auto it = legs_index.rbegin();
  auto end = legs_index.rend();
  for (; it != end; ++it)
    std::cout << it->name << '\n';
}

Отпечатки

spider
cat
shark
person sehe    schedule 01.09.2015
comment
В качестве альтернативы можно инвертировать предикат заказа: Жить на Coliru - person sehe; 02.09.2015
comment
спасибо за усилия. Я не думаю, что это мысль, после некоторого чтения, проб и ошибок я обнаружил, что проблема заключается в выборе методов индексации. Например, если вы выбрали ordered_non_unique в сочетании с sequenced, я получу то, что хочу. Но с hashed_unique я не буду использовать rbegin или rend для такого индекса. - person hebbo; 02.09.2015
comment
@hebbo На вопрос, который был задан, я думаю, что это правильно. В исходном вопросе не упоминаются хешированные индексы. хэш-индексы удовлетворяют требование С++ неупорядоченных ассоциативных контейнеров, которые не предоставляют обратных итераторов, поскольку обратная итерация будет давать такой же произвольный порядок, как и прямая итерация. - person Tanner Sansbury; 02.09.2015