为什么并行 for_each 需要前向迭代器?

Why does the parallel for_each require forward iterators?

我正在设计一个遍历多个容器的迭代器,因此有一个 return 类型的代理对象。因此,它能做的最好的事情就是成为一个输入迭代器(这是因为前向迭代器要求 reference 是一个实际的引用类型,而据我所知,这对于输入迭代器来说并非如此)。

(让我说)普通的 for_each 对我的迭代器来说就像一个魅力。
然而,当我查看它的并行版本时,我看到它只接受前向迭代器。因此我不能使用一个复杂的迭代器,它 return 是一个代理对象,这很烦人。
另一方面,我在网上查看了其他值得注意的实现,这并不像我最初想象的那么普遍——例如,英特尔 TBB 为每个接受输入迭代器的人提供了自己的并行。

我的问题是:为什么并行 std::for_each 不能与输入迭代器一起工作?
我看不出它们是前向迭代器的意义所在,因为乍一看,即使使用输入迭代器它也能正常工作。我错过了什么?

由于您指出的原因,C++17 迭代器模型存在一个已知缺陷,即代理迭代器只能是输入迭代器。这有很多缺点。并行算法不需要非代理迭代器,但它们肯定需要多遍保证。而当前的迭代器类别模型将两者混为一谈。

对于 C++20 范围,我们得到了 iterator_concept, which is a backwards-compatible shim to properly support proxy iterators. You can have an iterator_category of input_iterator_tag but an iterator_concept of forward_iterator_tag, for instance. The new ForwardIterator 概念的想法,而不是看类别,而是看概念:

template<class I>
  concept ForwardIterator =
    InputIterator<I> &&
    DerivedFrom<ITER_CONCEPT(I), forward_iterator_tag> &&
    Incrementable<I> &&
    Sentinel<I, I>;

并行算法是否会改变是另一个我无法回答的问题。

C++17 迭代器概念将前向迭代器定义为迭代器的最弱形式,需要同一范围内的多个迭代器才能运行。也就是说,您可以复制前向迭代器,递增副本,但仍然可以通过原始迭代器访问原始值。

纯 IntputIterator 概念只需要单遍。一旦你增加了一个迭代器,它的所有其他副本都变得无效。

能够并行化 for_each 最终需要每次并行调用都获得一组不同的迭代器和要操作的值。这意味着迭代器必须是可复制的并且独立于其他迭代器。这要求它们是前向迭代器。

现在是的,这意味着您不能将代理迭代器与并行 for_each 一起使用,即使您的迭代器 彼此独立的。这只是 C++17 迭代器概念模型的局限性。