我正在设计一个遍历多个容器的迭代器,因此将代理对象作为返回类型。因此,最好的办法是成为输入迭代器(这是因为前向迭代器要求reference
是实际的引用类型,而据我所知,这对输入迭代器而言并非如此)。
(让我说)普通for_each
就像我的迭代器一样具有魅力。
但是,当我查看其并行版本时,我发现它仅接受转发迭代器。因此,我不能使用复杂的迭代器来返回代理对象,这很烦人。
另一方面,我在网上寻找其他值得注意的实现方式,但这并不像我最初想象的那么普遍-例如,英特尔®TBB为每个接受输入迭代器的应用程序提供了自己的并行处理。
然后我的问题是:为什么并行std::for_each
不能与输入迭代器一起使用?
我看不到它们是正向迭代器的意义,因为乍一看它即使在输入迭代器中也能正常工作。我想念什么?
答案 0 :(得分:10)
由于您指出的原因,C ++ 17迭代器模型存在一个已知缺陷,即代理迭代器只能是输入迭代器。这有很多缺点。并行算法不需要非代理迭代器,但是肯定需要多遍保证。并且当前的迭代器类别模型将两者合并。
使用C ++ 20范围,我们得到iterator_concept
的概念,它是向后兼容的填充程序,可以正确地支持代理迭代器。例如,您可以拥有iterator_category
的{{1}}到input_iterator_tag
的{{1}}。新的ForwardIterator
概念不是针对类别,而是针对以下概念:
iterator_concept
并行算法是否会改变是另一个我无法回答的问题。
答案 1 :(得分:4)
C ++ 17迭代器概念将前向迭代器定义为迭代器的最弱形式,它需要在相同范围内运行多个迭代器。也就是说,您可以复制正向迭代器,增加副本,但仍可以通过原始迭代器访问原始值。
纯IntputIterator概念仅需要单遍。递增迭代器后,该迭代器的所有其他副本实际上将变得无效。
要能够并行化const intersection = (a1 = [], a2 = []) =>
{ const s =
new Set(a1)
return a2.filter(x => s.has(x))
}
const intersectAll = (a = [], ...more) =>
more.reduce(intersection, a)
console.log(intersectAll(['a', 'b'], ['b', 'c'], ['b', 'd'], ['e', 'b']))
// [ 'b' ]
,最终需要每次并行调用才能获得一组独特的迭代器和值进行操作。这意味着迭代器必须是可复制的并且独立于其他迭代器。这就要求它们成为正向迭代器。
现在是的,这意味着即使迭代器 彼此独立,也不能使用具有并行for_each
的代理迭代器。这只是C ++ 17迭代器概念模型的局限性。