Получение значений, не равных х в boost's multi_index_container - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь получить итератор для всех значений, которые не равны определенному значению в 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 Ответ

0 голосов
/ 27 февраля 2019

Обратите внимание, что equal_range(k) возвращает диапазон (пара итераторов в этом контексте), поскольку он основан на том факте, что элементы, ключ которых равен k, хранятся рядом вдоль последовательности контейнера:

enter image description here

С другой стороны, элементы, ключ которых равен , а не , равный k, не смежны, а принадлежат двум непересекающимсядиапазоны:

enter image description here

Таким образом, невозможно 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()));
}

Полный пример приведен ниже.

Live On Coliru

#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
...