如果我想累积std::vector
的绝对值,可以使用lambda来计算绝对值并将其添加到std::accumulate
(live demo)的总和中。 / p>
#include <numeric>
#include <vector>
int main (){
std::vector<int> vec {1,2,3,-4};
auto abs_val =[](auto val, auto sum){return sum + std::fabs(val);};
return std::accumulate(vec.begin(), vec.end(), 0, abs_val);
}
我想写
return std::accumulate(vec.begin(), vec.end(), 0, std::fabs());
但这不会编译,因为期望具有两个参数sum
和value
的函数。
有没有更优雅的方式来写这个?我需要lambda吗?我可以摆脱它吗?
答案 0 :(得分:6)
在C ++ 17之前
您基本上想做两件事:转换元素,然后对其求和。对于std::accumulate
,您必须告诉算法如何对元素求和,但是如果要转换元素,则需要做一些额外的事情。
您要编写的行仅告诉您如何转换元素(并且不会编译,因为accumulate
期望函子添加的元素不会转换元素)。
TL; DR:否。如果要转换和添加元素,则必须同时进行。没有称为transform_and_accumulate
的算法,因此您必须自己组合一些东西。
C ++ 17
以上内容仅在具有transform_reduce
并且基本上可以满足您需要的C ++ 17之前适用。
答案 1 :(得分:3)
您通过晶圆厂的方式有两个问题。第一个是微不足道的,另一个则涉及更多。您显示的代码无法正常工作,因为您正试图调用fab并将结果传递给std :: accumulate(float或double):
std::accumulate(vec.begin(), vec.end(), 0, std::fabs()); //note the parens ()
因此,如果std :: fabs只是一个功能,并且使用了正确的签名,那么它将起作用:
std::accumulate(vec.begin(), vec.end(), 0, std::fabs);
但是,如here所示,fabs在float,double和long double上重载,这意味着std :: fabs是一个重载集合,而不是一个函数,因此尚不清楚哪个版本满足您的需求想通过。问题的一部分在这里有一个答案:How do I specify a pointer to an overloaded function?
此外,如评论和其他答案所述,累加最后一个参数期望二进制运算将两个值组合在一起,而fab仅取一个绝对值。正确使用的算法是C ++ 17的transform_reduce:
std::transform_reduce(vec.begin(), vec.end(),0,std::plus<>{}, static_cast<double (*)(double)>(std::fabs));