为什么STL数值算法使用'op'而不是'op ='?

Dan*_*iel 8 c++ stl

为什么std::numeric算法似乎更喜欢op而不是op =?例如,以下是std::accumulateLLVM中的实现:

template <class _InputIterator, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
_Tp
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
{
    for (; __first != __last; ++__first)
        __init = __init + *__first;
    return __init;
}
Run Code Online (Sandbox Code Playgroud)

如果使用+=运营商实施,这不会更有效/更简洁/更好吗?

Zet*_*eta 15

它在标准中定义如下......

标准是根据而+不是+=:

26.7.2累积 [accumulate]

template <class InputIterator, class T>
  T accumulate(InputIterator first, InputIterator last, T init);
template <class InputIterator, class T, class BinaryOperation>
  T accumulate(InputIterator first, InputIterator last, T init,
               BinaryOperation binary_op);
Run Code Online (Sandbox Code Playgroud)

效果:通过acc使用初始值初始化累加器来计算其结果init,然后使用acc = acc + *i或按顺序修改范围内的 cc = binary_op(acc, *i)每个迭代器.i[first,last)

其他数值算法也是如此.

......而标准是基于STL ......

但这就是为什么他们现在这样实施的原因.但是,要了解原因,需要进一步深入兔子洞:

对类型的要求

对于第一个版本,带有两个参数的版本:

  • InputIterator 是输入迭代器的模型.
  • T 是可分配的模型.
  • 如果x是类型的对象Ty是的目的InputIteratorvalue类型,那么x + y被定义.
  • 返回类型x + y可转换为T.

......而STL是由...创建的?

那么,为什么呢?让我们问一下STL背后的思想亚历山大斯蒂芬诺夫:

[A]用户已经要求一个[问题]在计算器上两天前有关的像数值算法的实现和制剂 accumulateinner_product,它们在以下方面所定义+ 的,而不是+=(在ISO C++ 11 26.7节).

我试图找到决定背后的一些理由,但即使是SGI页面上的版本也未提及有关此特定运算符选择的任何内容.

是否根据您的个人偏好选择了运营商(a = a + b而不是+ = b),正如一些评论所假设的那样?当然,+ b是更自然的编写操作的方式吗?或者只是a = a + b和a = bin_op(a,b)之间的对称问题?

- [Zeta]

现在,在你阅读他的答案之前,请记住他大约30年前开始写一个通用的图书馆,他和孟李的初始文件标准模板图书馆将在今年10月成立二十周年.不用多说,我提出他的答案:

我怀疑这是a = a + b和a = bin_op(a,b)之间的对称问题,但我真的不记得了.我应该写一份理由文件,说明STL中不同设计选择之间的所有推理,但我没有.抱歉.

(如果斯捷潘诺夫有机会读到这个:再次感谢你的回答!)

个人认为Common Lisp的灵感reduce是另一个因素,但这只是猜测.

从中可以学到什么?

有时,标准中的决定是基于个人偏好和优雅.例如,如果Stroustrup写了STL,他就会"非常喜欢使用+ = b作为更直接的意图表达,通常比a = a + b更快".但是,我不得不承认a = a + b和a = bin_op(a,b)之间的对称性有其自身的美感.

话虽这么说,这个a+=ba=a+b争议将促进挑战:

当我们定义标准概念时,这个问题将变得非常重要,我不知道如何解决它.[Stroustrup的; 还要感谢他回答我的问题!]

就是这样,我希望你能享受到C++历史的一点点.

  • @Yakk:好吧.我写了一封电子邮件.对于错误的人,但至少我写了一个.Stroustrup本人会使用`+ =`,所以我认为这很可能是Stepanov的个人偏好.我明天会给他写一封电子邮件. (2认同)
  • 真棒!我只能赞成这一次,但我也可以提出上述问题.这是多年前做出的一个看似随意的决定.@Serthy在下面提出了一个很好的观点:如果你的类型为`T`,`int = int*T`和`int = T*int`重载,你可以累积到没有`binop`的`int`.但是,*没有办法重载`int*= T`*. (2认同)

Jer*_*fin 10

它可能更有效率,而且显然不那么冗长.

这种方式的通常原因是最小化对底层类型的要求.如果您使用过+=,则基础类型必须支持+=.对于类似的东西int那是微不足道的,并且已经存在,但你定义一个类,它完全有可能将定义+=,而不是化合物+=(在这种情况下,代码使用+=显然会失败).

  • 也许它是一种你不能进一步扩展的类型,唯一的方法是应用全局`operator`函数? (2认同)