0

我在一个类中有一个私有范围的 Boost.BiMap,我想导出这个地图的一部分的公共视图。我对以下代码有两个问题:

class Object {

    typedef bimap<
        unordered_set_of<Point>,
        unordered_multiset_of<Value>
    > PointMap;

    PointMap point_map;

public:
    ??? GetPoints(Value v) {
    ...
}

第一个问题是我的迭代方法是否Point与 a 相关联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 */
}

第二个问题是在???不暴露 bimap 迭代器的情况下提供 GetPoints(上面的返回类型)的公共视图的最佳方法是什么,因为调用者似乎必须知道point_map.right.end(). 任何有效的结构(例如引用列表或集合)都可以使用,但是我对如何创建集合有点迷茫。

谢谢!

4

1 回答 1

0

第一个问题:

由于您将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.htmlhttp://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; }
};

最好让它不可复制、不可移动和不可分配(就像我在上面通过删除相关的成员函数所做的那样),因为用户可能会保留代理类的副本,并在迭代器可能失效时尝试访问它.

第一种方式意味着编写更少的代码,第二种方式意味着向用户呈现一个更通用的接口(如果您稍后需要修改实现,则允许在代理类中隐藏更多内容)。

于 2012-01-28T20:23:26.867 回答