Первый вопрос:
Поскольку вы используете тип коллекции 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; }
};
Это хорошая идея, чтобы сделать его не копируемым, неподвижным и не назначаемым (как я сделал выше, удалив соответствующие функции-члены), поскольку в противном случае пользователь может сохранить копию прокси-класса и попытаться получить к ней доступ позже, когда итераторы может быть признано недействительным.
Первый способ означает написание меньшего количества кода, второй - представление пользователю более общего интерфейса (и позволяет скрыть больше вещей в прокси-классе, если вам потребуется изменить реализацию позже).