C++ standard wording: Does “through all iterators in the range” imply sequentiality?

谁说胖子不能爱 提交于 2019-11-27 22:43:56

In the discussion of LWG475, std::for_each is compared with std::transform. It's noted that "transform does not guarantee the order in which its function object is called". So, yes, the committee is aware of the lack of sequential guarantees in the standard.

There is no opposite requirement for non-sequential behavior either, so Microsoft and Apache are free to use sequential evaluation.

Anywhere the standard doesn't specify an ordering on an algorithm, you should assume that an implementation can exploit that for parallelism. The paper n3408 discusses options for parallelisation, and points to the Thrust library, which is both a usable parallel-enabled reimplementation of the standard algorithms and a proof-of-concept for future standardisation of parallelism in the algorithms.

Looking at Thrust's implementation of generate, it calls gen in a parallel loop whenever the iterator category is random access. As you've observed, this is consistent with the standard, so you should not assume that generate will always be sequential. (For example, a thread-safe std::rand can be efficiently used with generate and does not require sequential invocation.)

The only algorithms that guarantee sequential invocation are those in numeric; if your code depends on sequential invocation, you should use iota in place of generate. Adapting an existing generator:

template<typename F> struct iota_adapter {
   F f;
   operator typename std::result_of<F()>::type() { return f(); }
   void operator++() {}
};
template<typename F> iota_adapter<F> iota_adapt(F &&f) { return {f}; }

Use as:

#include <numeric>
#include <iostream>

int main() {
   int v[5], i = 0;
   std::iota(std::begin(v), std::end(v), iota_adapt([&i]() { return ++i; }));
   for (auto i: v) std::cout << i << '\n';
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!