【问题标题】:Expose public view of privately scoped Boost.BiMap iterator公开私有范围的 Boost.BiMap 迭代器的公共视图
【发布时间】:2012-02-21 06:40:13
【问题描述】:

我在一个类中有一个私有范围的 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-&gt;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()。任何有效的结构(例如引用列表或集合)都可以使用,但我对如何创建集合有点迷茫。

谢谢!

【问题讨论】:

    标签: c++ boost iterator bimap


    【解决方案1】:

    第一个问题:

    由于您在 bimap 类型的右侧使用 unordered_multiset_of 集合类型,这意味着它将具有与 std::unordered_multimap 兼容的接口。 std::unordered_multimap 具有成员函数 equal_range(const Key&amp; 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; }
    };
    

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

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

    【讨论】:

    • 关于第二个问题的第一种方法,PointMap是否需要公开范围?我可以为公共接口使用某种类型的通用迭代器吗?
    • PointMap 仍然可以是私有的。我的示例代码中的 typedef match_iterator 需要公开,以便类外的代码可以使用它。
    猜你喜欢
    • 2016-05-30
    • 2012-09-03
    • 1970-01-01
    • 2011-11-26
    • 2013-03-18
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    • 2021-06-04
    相关资源
    最近更新 更多