Предоставить публичное представление закрытого итератора Boost.BiMap
У меня есть класс Boost.BiMap в приватной области, и я хотел бы экспортировать публичное представление части этой карты. У меня есть два вопроса по поводу следующего кода:
class Object {
typedef bimap<
unordered_set_of<Point>,
unordered_multiset_of<Value>
> PointMap;
PointMap point_map;
public:
??? GetPoints(Value v) {
...
}
Первый вопрос, если мой метод итерации, чтобы получить Point
связан с Value
верно. Ниже приведен код, который я использую для перебора точек. Мой вопрос заключается в том, правильно ли я выполняю итерацию, потому что я обнаружил, что мне нужно включить it->first == value
условия, и я не был уверен, требуется ли это, учитывая лучший интерфейс, о котором я, возможно, не знаю.
PointMap::right_const_iterator it;
it = point_map.right.find(value);
while (it != point_map.right.end() && it->first == val) {
/* do stuff */
}
Второй вопрос заключается в том, каков наилучший способ обеспечить публичное представление GetPoints (???
тип возврата выше), не раскрывая итератор bimap, потому что кажется, что вызывающий должен знать о point_map.right.end()
, Любая эффективная структура, такая как список ссылок или набор, будет работать, но я немного растерялся, как создать коллекцию.
Спасибо!
1 ответ
Первый вопрос:
Поскольку вы используете unordered_multiset_of
тип коллекции для правой части типа bimap, это означает, что он будет иметь интерфейс, совместимый с std::unordered_multimap
, std::unordered_multimap
имеет функцию-член equal_range(const Key& key)
который возвращает std::pair
из итераторов, один указывает на первый элемент, который имеет желаемый ключ, и один, который указывает на один за концом диапазона элементов, имеющих тот же ключ. Используя это, вы можете выполнять итерацию по диапазону с соответствующим ключом, не сравнивая ключ со значением в условии итерации.
См. http://www.boost.org/doc/libs/1_41_0/libs/bimap/doc/html/boost_bimap/the_tutorial/controlling_collection_types.html и http://en.cppreference.com/w/cpp/container/unordered_multimap/equal_range для ссылок.
Второй вопрос:
Создание списка или другого фактического контейнера указателей или ссылок на элементы с совпадающими значениями и возвращение, которое неэффективно, поскольку для него всегда требуется пространство O(n), в то время как простое разрешение пользователю перебирать диапазон в исходном bimap требует только возвращает два итератора, которые требуют только O(1) памяти.
Вы можете написать функцию-член, которая возвращает итераторы напрямую, например:
typedef PointMap::right_const_iterator match_iterator;
std::pair<match_iterator, match_iterator> GetPoints(Value v) {
return point_map.right.equal_range(v);
}
или вы можете написать прокси-класс, который представляет контейнероподобный интерфейс, имея функции-члены begin() и end(), возвращающие эти два итератора, и GetPoints()
функция-член возвращает объект этого типа:
class MatchList {
typedef PointMap::right_const_iterator iterator;
std::pair<iterator, iterator> m_iters;
public:
MatchList(std::pair<iterator, iterator> const& p) : m_iters(p) {}
MatchList(MatchList const&) = delete;
MatchList(MatchList&&) = delete;
MatchList& operator=(MatchList const&) = delete;
iterator begin() { return m_iters.first; }
iterator end() { return m_iters.second; }
};
Хорошей идеей будет сделать его не копируемым, неподвижным и не назначаемым (как я сделал выше, удалив соответствующие функции-члены), так как в противном случае пользователь может сохранить копию прокси-класса и попытаться получить к ней доступ позже, когда итераторы могут быть аннулированы.,
Первый способ означает написание меньшего количества кода, второй означает представление пользователю более общего интерфейса (и позволяет скрыть больше вещей в прокси-классе, если вам потребуется изменить реализацию позже).