编写一个迭代器,使几个容器看起来像一个

时间:2011-07-19 13:33:42

标签: c++ boost iterator

考虑以下简化示例和所需输出:

class A
{
    class combined_iterator
    {
        ????
    }
    typedef ??? t_combined_it;

    t_combined_it begin();
    t_combined_it end();

    std::vector<int> m_Vec1, m_Vect2;
}

A a;
a.m_Vec1.push_back(1);
a.m_Vec2.push_back(2);
for (A::t_combined_it it = a.begin() ; it != a.end() ; it++) {
     std::cout << *it << " ";
}

输出:

1 2 

我认为问题很清楚:如何编写一个迭代器,使其看起来好像两个或多个其他迭代器实际上只是一个序列。因此,在示例中,我可以使用迭代器,而不是迭代m_Vec1和m_Vec2,迭代首先迭代m_Vec1的元素,然后透明地迭代m_Vec2。

我发现以下问题我认为是相同的:Make a c++ iterator that traverses 2 containers。这个问题没有好的答案;原始提问者提出的解决方案似乎很复杂,而且(相对)内存密集型。

我尝试了一种天真的方法,将std :: vector :: iterator保留为我的自定义迭代器的一个成员,并将其与迭代的每个序列的.end()迭代器进行比较;然而,似乎比较来自不同容器的迭代器是非法的(我希望它们只是为了返回'不相等' - 也许这是找到这个问题的解决方案的方向?我想不出如何但是要实现它。

在可能的情况下,如果相关,我想使用boost :: iterators,因为我在别处使用它们,我喜欢它为我的迭代器实现提供的同质性;但是当然如果有人在不使用它们的情况下有了一个想法,我可以自己动手,所以从那时起就不需要它们。

6 个答案:

答案 0 :(得分:19)

boost::join正是您要找的。您还可以研究实现,尤其是如何为容器遍历,引用和返回值类型派生最小公分母。引用:

  

连接功能的目的是将两个范围连接到一个更长的范围。

     

结果范围将具有作为参数提供的两个范围的最低公共遍历。

     

请注意,由于需要检查范围的结尾是否>>,因此连接范围会产生性能成本。在遍历期间已经到达内部。

答案 1 :(得分:7)

我认为你的“天真”方法应该有效,并进行以下更改:不是将迭代器与每个容器的end()进行比较,而是保持指向当前容器的指针并进行比较迭代器只有当前容器的end()。到达终点时,继续前进到下一个容器。这样,你永远不会将迭代器与另一个容器进行比较,而不是它所指向的容器。这也很容易推广到任意大小的集合集合。

答案 2 :(得分:3)

如果要并行迭代两个迭代器,

zip_iterator可以正常工作。如果需要按顺序迭代容器,可以使用iterator_adaptor实现一个容器。

答案 3 :(得分:3)

我已经为不同的问题实现了类似的东西。实施是here。您接洽的基本思路是:存储两个迭代器范围,当您被要求执行操作时,检查您是否已完成第一个范围内的迭代,并使用任一范围。

这绝不是线程安全的,我从未在实际代码中使用过该实现,因此可能存在问题和错误......

答案 4 :(得分:1)

其他人的答案仅用于加入两个范围,但不是任意数量的范围。

PStade Oven has a concatenated adaptor用于加入任何数量的范围;它还有一个jointed适配器,用于连接2个范围,具体而言。

如果需要,您当然可以使用begin()end()将范围转换为迭代器;只需确保范围超过迭代器。

答案 5 :(得分:0)

Aasmund是对的。你的方法虽然简单但应该有效。但是还有很大的优化空间。

集合对象通常很大,因此需要一些时间来迭代。特别是列表和数组。

您应该考虑多线程,以便可以并行迭代每个集合。

此外。您应该接受链接使用的帖子的建议并使用

Boost.MultiIndex的