当仅用一个模板即可完成工作时,为什么在C ++中累加器定义了两个模板(一个模板带有binaryOperation
,默认值是sum)?
我指的是http://www.cplusplus.com/reference/numeric/accumulate/
答案 0 :(得分:9)
因为这就是标准的指定方式。
使用重载还是默认参数通常是一个问题。在这种情况下,选择了超载(由委员会,亚历山大·斯蒂芬诺夫(Alexander Stepanov)或碰巧负责选择的人)。
默认值比重载更受限制。例如,可以有一个指向第一个重载的函数指针T (*)(InputIterator, InputIterator, T)
,如果只有一个带有4个参数的函数(模板),则不可能。可以将这种灵活性用作使用重载的参数,而不是默认参数。
答案 1 :(得分:6)
确实,您可以从单个模板中获得几乎相同的行为
template <class InputIt, class T, class BinaryOperation = std::plus<>>
accumulate(InputIt first, InputIt last, T init, BinaryOperation op = {});
但是请注意,在早期版本的C ++中,这将是困难或不可能的:
std::plus<>
(与std::plus<void>
相同)无效:类模板只能用一种特定的参数类型实例化。accumulate
模板甚至比1998年的第一个C ++标准还早:它可以追溯到SGI STL库。当时,编译器对模板的支持相当不一致,因此建议使模板尽可能简单。因此保留了原始的两个声明。如bobah's answer中所述,将它们组合成一个声明可能会破坏现有代码,因为例如代码可能使用指向三参数版本实例化的函数指针(并且函数指针不能表示默认函数参数,无论是否该功能是否来自模板)。
有时,标准库会为现有函数添加其他重载,但通常仅出于特定目的,这将改善接口,并在可能的情况下不破坏旧代码。 std::accumulate
没有任何这样的原因。
(但是注解,标准库中的成员函数比std::accumulate
之类的非成员函数可以更频繁地进行更改。标准允许实现声明具有不同重载,默认参数等的成员函数,声明长度不同于指定的长就像描述的那样。这意味着将指向成员函数的指针指向标准库类成员,或者首先假设非常具体的声明,通常是个坏主意。)
答案 2 :(得分:0)
使用这两个函数的动机与我们同时拥有copy
和transform
函数的原因相同,这使编码人员可以灵活地在每个元素的基础上应用函数。但是也许一些现实世界的代码将有助于理解将在何处使用它。我已经在编码中专业使用了这两个片段:
accumulate的1 st 实例可用于求和范围的元素。例如,给定const int input[] = { 13, 42 }
,我可以这样做以获取input
中所有元素的总和:
accumulate(cbegin(input), cend(input), 0) /* Returns 55 */
我个人最常使用2 nd 实例生成string
(因为它是c++与join
最接近的东西),但是它可以当添加元素之前需要特殊的预处理时,也可以使用此方法。例如:
accumulate(next(cbegin(input)), cend(input), to_string(front(input)), [](const auto& current_sum, const auto i){ return current_sum + ", " + to_string(i); }) /* Returns "13, 42"s */
在考虑使用2 nd 函数时,值得注意P0616R0。该建议已被c++20接受,并且将移动而不是将第一个参数复制到accumulate
的函子中,该函子“可以带来巨大的改进(特别是,它可以
表示累加string
是线性的而不是二次的。”