I'm wondering why functors are passed by copy to the algorithm
functions:
template <typename T> struct summatory
{
summatory() : result(T()) {}
void operator()(const T& value)
{ result += value; std::cout << value << "; ";};
T result;
};
std::array<int, 10> a {{ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 }};
summatory<int> sum;
std::cout << "\nThe summation of: ";
std::for_each(a.begin(), a.end(), sum);
std::cout << "is: " << sum.result;
I was expecting the following output:
The summation of: 1; 1; 2; 3; 5; 8; 13; 21; 34; 55; is: 143
But sum.result
contains 0
, that is the default value assigned in the ctor. The only way to achieve the desired behaviour is capturing the return value of the for_each
:
sum = std::for_each(a.begin(), a.end(), sum);
std::cout << "is: " << sum.result;
This is happening because the functor is passed by copy to the for_each
instead of by reference:
template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
So the outer functor remains untouched, while the inner one (which is a copy of the outer) is updated and is returned after perform the algorithm (live demo), so the result is copied (or moved) again after doing all the operations.
There must be a good reason to do the work this way, but I don't really realize the rationale in this design, so my questions are:
- Why the predicates of the sequence-operation algorithms are passed by copy instead of reference?
- What advantages offers the pass-by-copy approach in front of the pass-by-reference one?
for ( int i : a ) { sum( i ); }
– Pinnafor_each( ..., just_cout_arg_to_std_out<int>() )
wouldn't be compiled – Pinnastd::accumulate
to do a sum, and if you need a stateful predicate you can always store the state external to the predicate. – Marsha