Предоставить публичное представление закрытого итератора Boost.BiMap - PullRequest
0 голосов
/ 28 января 2012

У меня есть класс 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 Ответ

0 голосов
/ 29 января 2012

Первый вопрос:

Поскольку вы используете тип коллекции 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; }
};

Это хорошая идея, чтобы сделать его не копируемым, неподвижным и не назначаемым (как я сделал выше, удалив соответствующие функции-члены), поскольку в противном случае пользователь может сохранить копию прокси-класса и попытаться получить к ней доступ позже, когда итераторы может быть признано недействительным.

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

...