Получение значений, не равных х в boost's multi_index_container
Я пытаюсь получить итератор для всех значений, которые не равны определенному значению в boost::multi_index_container
,
Индекс, к которому я хочу получить доступ, hashed_non_unique
целое число. С помощью equal_range(0)
в моем контейнере, который служит базой данных сопоставления, я могу получить доступ ко всем записям контейнера, для которых этот конкретный индекс равен нулю.
Что мне нужно, это функция, которая возвращает мне все записи, где индекс не равен нулю. Я искал в Интернете часами и нашел только перегруженную функцию
std::pair<iterator,iterator> equal_range(
const CompatibleKey& x,
const CompatibleHash& hash,const CompatiblePred& eq)const;
Но в документации по бусту есть только несколько примеров, и для этой конкретной проблемы их нет. Я не знаю, что такое CompatibleHash или CompatiblePred, но я пытался с:
m_mappingDb->get<tags::myIndex>().equal_range(m_mappingDb->begin(), 0,
[=](uint32_t lhs, uint32_t rhs) { return lhs != rhs; });
после нахождения примеров людей, использующих лямбду в качестве функции сортировки в multi_index_container
,
При компиляции я получаю C2664 в том лямбда-выражении, которое boost::multi_index::detail::hashed_index_iterator<Node,BucketArray,Category>
в uint32_t
это невозможно. Итак, я ожидаю, что моя лямбда должна использовать итераторы в качестве параметров, но какие именно? Что такое Node, BucketArray и Category?
В этом лямбда-выражении есть еще один C2064, который утверждает, что это не функция, которая принимает 1 аргумент. Конечно, это занимает 2. Должен ли я сравнить с этим вместо этого?
Моя альтернатива заключается в использовании lower_bound
а также upper_bound
вместо этого установите нижнюю границу равной 1, а верхнюю - максимальную величину uint32_t. Но, на мой взгляд, это ужасно ужасно. Должен быть правильный способ реализовать что-то вроде функции не равных.
1 ответ
Обратите внимание, что equal_range(k)
возвращает диапазон (пара итераторов в этом контексте), поскольку он опирается на тот факт, что элементы, ключ которых k
хранятся рядом вдоль последовательности контейнера:
С другой стороны, элементы, ключ которых не равен k
не являются смежными, но принадлежат двум непересекающимся диапазонам:
Так нет пути equal_range
можно повернуть, чтобы вернуть эту пару диапазонов. Если вам абсолютно необходимо рассматривать два диапазона как один логический диапазон, вы можете прибегнуть к Boost.Range's join
:
template<typename Container,typename Key>
auto not_equal_range(const Container& c,const Key& k)
{
auto rng=c.equal_range(k);
return boost::range::join(
boost::make_iterator_range(c.begin(),rng.first),
boost::make_iterator_range(rng.second,c.end()));
}
Полный пример приведен ниже.
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/join.hpp>
template<typename Container,typename Key>
auto not_equal_range(const Container& c,const Key& k)
{
auto rng=c.equal_range(k);
return boost::range::join(
boost::make_iterator_range(c.begin(),rng.first),
boost::make_iterator_range(rng.second,c.end()));
}
using namespace boost::multi_index;
using container=multi_index_container<
int,
indexed_by<
hashed_non_unique<identity<int>>
>
>;
#include <iostream>
int main()
{
container c={0,0,1,1,2,2,3,4,4,4,5,6,6,6,7};
for(auto x:not_equal_range(c,4))std::cout<<x<<" ";
}
Выход
0 0 1 1 2 2 3 5 6 6 6 7