考虑以下简化示例和所需输出:
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,因为我在别处使用它们,我喜欢它为我的迭代器实现提供的同质性;但是当然如果有人在不使用它们的情况下有了一个想法,我可以自己动手,所以从那时起就不需要它们。
答案 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的