Because you use 0
as the last parameter (the "initial value"), which is of type int
; and this deduces T = int
. (*)
I recommend to use foo.value_type()
as the last parameter. This evaluates to zero for primitive types such as int
, float
, double
, etc.
You can wrap this in a function template accumulate_zero
to save some redundant work if needed often. The following function template implements this by setting T
to the value type of the passed iterator:
template<class InputIt,
class BinaryOperation,
class T = typename std::iterator_traits<InputIt>::value_type>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
T accumulate_zero(InputIt first, InputIt last, BinaryOperation op)
{
return std::accumulate(first, last, T(), op);
// ^^^
}
(*) That's simply how type deduction works. std::accumulate
is a function template with, among others, the type T
being a template parameter. If not given explicitly and if possible, it is deduced from the passed argument's type.