ISO/ IEC JTC1/SC22/WG21 N4405

The type of the accumulaters of standard algorithms 
std::accumulate and std::inner_product.

Document number: N4405

Project: Programming Language C++, Library Evolution Working Group

Date: 2015-02-11
Reply-To: Vladimir Grigoriev (vlad.moscow@mail.ru)

Preface. 

In the description of algorithms std::accumulate and std::inner_product there is said nothing about what type have internally used accumulators of the algorithms. This results in that  implementations of the algorithms can have different behaviours.

For example if algorithms std::accumulate is defined like

template <class InputIterator, class T>

T accumulate( InputIterator first, InputIterator last, T init )

{

	T acc = init;



	for ( ; first != last; ++first ) acc = acc + *first;
	

	return acc;

}


then the following program

#include <iostream>
#include <numeric>
#include <iterator>

int main() 

{

	int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

	

	std::cout << std::accumulate<decltype( std::begin( a ) ), const int>

	                             ( std::begin( a ), std::end( a ), 0 )
	          << std::endl;



	return 0;

}

will not compile.

On the other hand if to define the algorithm like

template <class InputIterator, class T>

T accumulate( InputIterator first, InputIterator last, T init )

{

	auto acc = init;



	for ( ; first != last; ++first ) acc = acc + *first;
	

	return acc;

}


then the above program will compile successfully.

Another example. Sometimes there is a sense to declare
explicitly the template argument that corresponds 
to initializer init as reference that to achieve 
more effectiveness of the algorithms 
by means of avoiding of creating of temporary objects.

However not all implementations of the algorithms can compile for example the following program

#include <iostream>

#include <iterator>



int main() 

{

	int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };


	long long acc = 0;



	accumulate<decltype( std::begin( a ) ), long long &>
	
	           ( std::begin( a ), std::end( a ), acc );



	std::cout << acc << std::endl;



	return 0;

}

Thus the description of the algorithms in the C++ Standard
should explicitly contain words about how the accumulators
of the algorithms are defined that to avoid the ambiguity
in the algorithms' implementations.

Changes to the C++ Standard.

Section 26.7.2 Accumulate.

Change paragraph #1 the following way

1 Effects: Computes its result by defining the accumulator acc like T acc
(T may be a reference type) and initializing it with the initial value
init and then modifies it with acc = acc + *i 
or acc = binary_op(acc, *i) for every iterator i 
in the range [first,last) in order.289 

Section 26.7.3 Inner product

Change paragraph #1 the following way

1 Effects: Computes its result by defining the accumulator
like T acc (T may be a reference type) and initializing it with the initial value
init and then modifying it with acc = acc + (*i1) * (*i2)
or acc = binary_op1(acc, binary_op2(*i1,*i2)) 
for every iterator i1 in the range [first1,last1) 
and iterator i2 in the range [first2,first2
+ (last1 - first1)) in order.