#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;
}
Я хочу иметь возможность,
- Получить значения, не являющиеся уникальными идентификаторами, сопоставленными с
- Получить значение (если оно существует), которому соответствует уникальный идентификатор
Пожалуйста, дайте мне знать правильный / самый простой способ сделать это. Также я не использую 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::iterator 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
ishashed_non_unique
. Возможно, вы захотите перепроверить свои настройки в реальном коде и / или использовать отладочные выходные данные всего контейнера (путем обхода его по произвольному индексу), чтобы убедиться, что он содержит то, что вы думаете, что он делает.5. @Agnew, я проверю это, спасибо, что указали на это. Я хотел просмотреть контейнер и посмотреть, что он содержит, но я нашел mi_StoreMe::begin(), mi_StoreMe()::end() или это, но не смог найти mi_StoreMer::iterator. Как мне выполнить итерацию всего этого (без использования списка ключей). Фактически, это была моя первая идея для отладки этого. Пожалуйста, дайте мне знать, как я получаю все значения, хранящиеся в m_StoreMe. Спасибо