Accumulate absolute values of a vector

Before C++17

You basically want to do two things: Transform the elements and then sum them. For std::accumulate you have to tell the algorithm how you want to sum the elements up, but if you want to transform the elements, you need to do something extra.

The line you want to write only tells how to transform the elements (and it doesnt compile, because accumulate expects a functor that adds elements not one that transforms them).

TL;DR: No. If you want to transform and add elements, you have to do both. There is no algorithm called transform_and_accumulate, so you have to combine something yourself.

C++17

The above is true only till C++17, which has transform_reduce and that basically does what you are looking for.


There are two issues with the way you would like to pass fabs. The first is trivial, the other one somewhat more involved. The code you showed cannot work, as you are trying to call fabs and pass the result to std::accumulate(a float or double):

std::accumulate(vec.begin(), vec.end(), 0, std::fabs()); //note the parens ()

So, if std::fabs were simply one function and used the correct signature this would work:

std::accumulate(vec.begin(), vec.end(), 0, std::fabs);

Yet, as can be seen here, fabs is overloaded on float, double and long double, meaning std::fabs is an overload set, not one single function and as such it's not clear which versions address you would like to pass. That part of the question has an answer here: How do I specify a pointer to an overloaded function?

Furthermore, as stated in the comments and other answer, accumulates last parameter expects a binary operation combining two values, whereas fabs only takes the absolute value of one. The correct algorithm to use is C++17's transform_reduce:

std::transform_reduce(vec.begin(), vec.end(),0,std::plus<>{}, static_cast<double (*)(double)>(std::fabs));