Получение значений из boost::multi_index

#c #boost #multi-index #boost-multi-index

#c #boost #многоиндексный #boost-многоиндексный

Вопрос:

Я boost::multi_index успешно создал и вставил значения. У меня есть два хэшированных индекса для multi_index. Обе функции являются функциями-членами, но одна уникальна, а другая неуникальна.

Я пытаюсь выяснить способ получения значений из контейнера, используя значения хэшей. Я не мог понять, как я должен это сделать. Я искал в Интернете, и я вижу, что многие люди задавали этот вопрос. Но я не понимаю, что нужно сделать. Я видел несколько решений в C 11, но я не использую C 11 и не понимаю, что делается. Может кто-нибудь, пожалуйста, объяснить мне, как это использовать? Ниже приведен мой код,

 #include "stdafx.h"
#include<multi_index_container.hpp>
#include<boost/multi_index/hashed_index.hpp>
#include<boost/multi_index/mem_fun.hpp>
#include<boost/multi_index/tag.hpp>



class RetClass
{
    int a, b;
};

class StoreMe
{
    RetClass ex;
    std::string exStr;
    int id;
public:
    void setId(RetClass a) 
    {
        ex = a;
    };


    virtual const RetClassamp; getId() const { return ex; }
    virtual std::string getIdString() const { return exStr; }
    int getUniqueId() const { return id; }
};

struct IndexByStringId{};
struct IndexByUniqueId{};

typedef boost::multi_index_container<
    StoreMe,
    boost::multi_index::indexed_by<
        boost::multi_index::hashed_unique<
            boost::multi_index::tag<IndexByStringId>,
            boost::multi_index::const_mem_fun<StoreMe, std::string,     amp;StoreMe::getIdString> 
        >,
        boost::multi_index::hashed_non_unique<
            boost::multi_index::tag<IndexByUniqueId>,
            boost::multi_index::const_mem_fun<StoreMe, int,     amp;StoreMe::getUniqueId> 
        >
    >
> mi_storeMe;

int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}
  

Я хочу иметь возможность,

  1. Получить значения, не являющиеся уникальными идентификаторами, сопоставленными с
  2. Получить значение (если оно существует), которому соответствует уникальный идентификатор

Пожалуйста, дайте мне знать правильный / самый простой способ сделать это. Также я не использую C 11.

Ответ №1:

Вот как вы могли бы извлекать значения из индекса на основе строк:

 mi_storeMe container;

std::string needle = whatToSearchFor();
auto iterator = container.get<IndexByStringId>().find(needle);
if (iterator != container.get<IndexByStringId>().end())
  found(*iterator);
else
  notFound();
  

Для индекса на основе идентификатора это очень похоже:

 mi_storeMe container;

RetClass needle = whatToSearchFor();
auto range = container.get<IndexByUniqueId>().equal_range(needle);
processRangeFromTo(range.first, range.second);
  

В ответе используется auto из C 11, чтобы я мог избежать указания соответствующих типов. Если у вас нет доступа к C 11, пожалуйста, сделайте вывод типа самостоятельно, прочитав multi_index документацию Boost. Я не могу ручаться за правильность, но я считаю, что тип итератора может быть записан как

 mi_storeMe::index<IndexByStringId>::type::iterator
  

По касательной: как выполнить отладку контейнеров с несколькими индексами в стиле printf без C 11.

Прежде всего, помните, что, хотя у вас этого нет auto , у вас все еще есть вывод типа в шаблонах. Нет необходимости указывать типы, если шаблон функции может их вывести:

 template <class It>
void printContainerItems(It from, It to) {
  for (; from != to;   from)
    print(*from);
}

printContainerItems(container.begin(), container.end());
  

Во-вторых, вы можете легко выполнять итерацию по индексу:

 const mi_Container::index<IndexByIdString>::typeamp; index = container.get<IndexByIdString>();
for (
  mi_Container::index<IndexByIdString>::type::iterat‌​or it = index.begin(), end = index.end();
  it != end;
    it
)
{
  operate_on(*it);
}
  

Комментарии:

1. Это нормально @Agnew? std::pair<mi_Container::index<IndexByIdString>::type::iterator, mi_Container::index<IndexByIdString>::type::iterator> range_it = Containers.get<IndexByIdString>().equal_range(nonEqId); if (range_it.first != Containers.get<IndexByIdString>().end()) //If it was found {//We might have a range of values for (mi_Container::index<IndexByIsString>::type::iterator it = range_it.first; it != range_it.second; it ) { value = *it; //Get the value pointed by the iterator, do what I want on "value" . . .

2. @codeworks На первый взгляд все выглядит нормально, но почему бы вам не спросить свой компилятор и программу? 😉

3. @Agnew, я уже проверил. Я отправил сообщение для подтверждения, поскольку equal_range возвращает пустой диапазон (т. Е. Первый и последний итераторы, равные end())

4. @codeworks Обратите внимание, что в вашем Q IndexByStringId есть hashed_unique , а IndexByUniqueId is hashed_non_unique . Возможно, вы захотите перепроверить свои настройки в реальном коде и / или использовать отладочные выходные данные всего контейнера (путем обхода его по произвольному индексу), чтобы убедиться, что он содержит то, что вы думаете, что он делает.

5. @Agnew, я проверю это, спасибо, что указали на это. Я хотел просмотреть контейнер и посмотреть, что он содержит, но я нашел mi_StoreMe::begin(), mi_StoreMe()::end() или это, но не смог найти mi_StoreMer::iterator. Как мне выполнить итерацию всего этого (без использования списка ключей). Фактически, это была моя первая идея для отладки этого. Пожалуйста, дайте мне знать, как я получаю все значения, хранящиеся в m_StoreMe. Спасибо