2014-12-23 1 views
2

У меня есть запись с двумя полями (например, A и B). 2 экземпляра записи должны считаться равными, если их As равны. С другой стороны, коллекция экземпляров записей должна сортироваться по полю B.Контейнер C++ для хранения отсортированных уникальных значений с разными предикатами для сортировки и уникальности

Есть ли контейнер, такой как std :: set, который может быть определен с двумя разными предикатами, один для сортировки и один для уникальности, чтобы я мог избежать явной сортировки и просто добавлять элементы? Если нет, как это можно обойти?

Привет,

+0

Почему бы не использовать 'std :: set' и реализовать' operator <'в терминах' record :: B' и 'operator ==' в терминах 'record :: A'? –

+0

@TheParamagneticCroissant Поскольку 'std :: set' не использует' == 'вообще? Это означает, что он позволит дублировать элементы по семантике OP. – Angew

+0

@Angew [cppreference говорит мне] (http://en.cppreference.com/w/cpp/container/set/operator_cmp): «Ключ» должен отвечать требованиям «EqualityComparable», это неправильно? –

ответ

1

Существует ли контейнер, как станд :: набор, который может быть определен с двумя различными предикатами, по одному для сортировки и один для единственности

станда :: набора определяет, будет ли конкретный элемент является уникальным ИЛИ не с точки зрения критериев сортировки, которые вы ему предоставляете (по умолчанию он использует меньше <>). Нет необходимости явно передавать другие критерии проверки равенства элементов. С учетом сказанного, однако, вы можете использовать предикат с алгоритмами для проверки равенства элементов std :: set.

4

В стандартной библиотеке нет ничего, что могло бы поддержать ваш случай использования напрямую. Однако для этой цели вы можете использовать Boost.MultiIndexContainer. Что-то вроде этого:

typedef multi_index_container< 
    Record, 
    indexed_by< 
    ordered_non_unique<member<Record, decltype(Record::B), &Record::B>>, 
    hashed_unique<member<Record, decltype(Record::A), &Record::A>> 
    > 
> RecordContainer; 

(код предполагая правильные заголовки и using namespace директивы для краткости).

Идея состоит в создании контейнера с двумя индексами, который гарантирует заказ на основе B, а другой, который гарантирует уникальность на основе A. decltype() в коде могут быть заменены действительными типами A и B, которые вы знаете, но я этого не делаю.

Порядок индексов имеет незначительное значение, поскольку для удобства сам контейнер предлагает тот же интерфейс, что и его первый индекс. Тем не менее, вы всегда можете получить доступ к любому индексу, используя container.get().

Код не предназначен в качестве копия &. Вставить раствор, но в качестве отправной точки. Вы можете добавить настройки, индексные теги и т. Д. Подробнее см. В документации Boost.