Why only add?
No need to ask, he's a Smooth operator, smooth operator, smooth operator, smooth operator.
We have seen how to implement a generic sum. If we want to compute the maximum of a sequence, we know what to do:
template<typename Iterator, typename T>
T
max(Iterator a, Iterator a_end, value<T> init)
{
T res = init;
for(; a != a_end; ++a)
res = std::max(res, *a);
return res;
}
Stop, Stop, STOP!
Can't we achieve this in a simpler way?
We can see that max
is structurally identical to sum
.
Except the line computing the maximum of two operands instead of their sum.
By consequence, if we parametrize this operation as well,
we obtain a generic function which can do both (and much more ...).
template<typename Iterator, typename T, typename BinOp>
T reduce(Iterator begin, Iterator end, value<T> init, BinOp op)
{
T res = init;
for(; begin != end; ++begin)
res = op(res,*begin);
return res;
}
Using reduce
We get back our sum,
when we pass the built-in addition operator to reduce
:
double a[N] = { ... };
double suma = reduce(a, a+N, 0.0, std::plus<double>());
The only difference to our sum
implementations
is, that now
res = res + *begin
is called
instead of res += *begin
.
For built-in types the compiler should produce identical code,
but for user-defined types this can be a performance loss.
This is a topic for a different article.
Of course, products can be computed in exactly the same way:
matrix4 pose = reduce(matrices.begin(), matrices.end(), matrix4::unit(), std::multiplies<matrix4>());
For computing the maximum, we should be able to use std::max
...?
Yes, but with the difference that std::max
is a function template and std::plus
is a class template, thus the syntax is slightly different:
double a[N] = { ... };
double maxa = reduce(a, a+N, ???, std::max<double>);
Um ... what about init
?
Is there a neutral element for maximum?
Times stay interesting ...