C ++的标准写法:请问“通过在范围内的所有迭代器”暗示顺序性?(C++ standard word

2019-07-19 17:37发布

这太问题引发了有关讨论std::generate和标准作出的保证。 特别是,你可以使用与内部状态函数对象和依靠generate(it1, it2, gen)调用gen()结果存储在*it ,称之为gen()再次,存放于*(it + 1)等,或者可以将它开始在后面,例如?

标准(n3337,§25.3.7/ 1)这样说:

效果:第一种算法调用函数对象gen ,并通过在所述范围内的所有的迭代分配根的返回值[first,last) 。 第二算法调用函数对象根,并通过在所述范围内的所有的迭代分配根的返回值[first,first + n)如果n为正,否则不做任何事。

好像没有顺序有保证,特别是因为其他段落有更强烈的措辞,例如std::for_each作用:适用f在范围每次提领迭代器的结果[first,last) ,从第一个开始,进行到last - 1 如果我们采取这一从字面上看,它只能保证开始在first ,并在结束last虽然-对顺序没有担保之间)。

但是:无论微软和Apache的C ++标准库既给那些需要的评价是连续的文档页面的例子。 而且两者的libc ++(在algorithm )和libstdc ++(以bits/stl_algo.h )实现它的方式。 此外,你失去了很多潜在的应用generate没有这种保证。

请问目前的措辞暗示顺序性? 如果不是,这是由委员会或故意的成员组成的监督?

(我清楚地知道,没有多少人谁可以提供有见地的回答这个问题,而不只是投机或讨论,但在我的愚见,这并没有使这个问题“没有建设性”按SO指导。)


由于@juanchopanza指出这个问题,并提到我对段落for_each

Answer 1:

在讨论LWG475 , std::for_each与比较std::transform 。 它指出,“ transform并不能保证在其功能对象调用的顺序。” 所以,是的,委员会意识到在标准缺乏连续的保证。

有非连续的行为没有对任何要求,因此微软和Apache是​​免费使用顺序计算。



Answer 2:

任何地方的标准没有规定的算法排序,你应该假设的实现可以利用该并行性。 本文n3408讨论到用于并行化选项,以及点推力库,它是的标准算法都可用启用并行重新实现和用于在算法的并行性将来标准化的证明的概念。

综观推力的实现的generate ,它调用gen在并行循环每当迭代器种类是随机的访问。 正如你所观察到的,这是与标准一致的,所以你不应该假设generate永远是连续的。 (例如,线程安全std::rand可以有效地与用于generate ,并且不需要连续调用。)

这保证顺序调用的唯一的算法是那些在numeric ; 如果你的代码依赖于顺序调用,你应该使用iota到位的generate 。 适配现有的发电机:

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}; }

用于:

#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';
}


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