Die arithmetische Operation kann ebenfalls parametrisiert werden.Im Ergebnis erhält man eine allgemeine Reduktion, analog std::accumulate.

Warum nur addieren?

We move in space with minimum waste and maximum joy. [...]
No need to ask, he's a Smooth operator, smooth operator, smooth operator, smooth operator.
Sade Adu (from the song Smooth Operator)

Nun haben wir gesehen, wie wir eine generische Summe implementieren können. Wenn wir jetzt das Maximum einer Sequenz ausrechnen wollen, wissen wir, was wir zu tun haben:

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;
}

Halt, halt, HAAALT!

Geht das nicht einfacher? Unser max sieht doch strukturell genauso wie die Summe aus. Bis eben auf die Zeile, die statt einer Summe zweier Operanden ihr Maximum berechnet. Also müssten wir genau diese Operation auch noch parametrisieren, dann erhalten wir eine generische Funktion, die beides kann (und noch viel mehr ...):

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;
}

Reduce benutzen

Unsere Summe erhalten wir, indem wir den eingebauten Additions-Operator an reduce übergeben:

double a[N] = { ... };
double suma = reduce(a, a+N, 0.0, std::plus<double>());

Einziger Unterschied zu vorher ist es, dass jetzt res = res + *begin anstelle res += *begin aufgerufen wird. Für eingebaute Typen sollte der Compiler identischen Code erzeugen, aber für selbstdefinierte Typen kann das einen Performance-Verlust bedeuten. Hierauf werde ich in einem späteren Artikel noch eingehen.

Genauso können wir natürlich Produkte berechnen:

matrix4 pose = reduce(matrices.begin(), matrices.end(), matrix4::unit(), std::multiplies<matrix4>());

Für die Maximums-Berechnung könnten wir doch std::max nehmen ... oder? Ja, mit dem Unterschied, dass std::max ein Funktions-Template ist und std::plus ein Klassen-Template, daher ist die Syntax leicht unterschiedlich:

double a[N] = { ... };
double maxa = reduce(a, a+N, ???, std::max<double>);

Öhm ... was nehmen wir denn jetzt für init? Gibt es denn überhaupt ein neutrales Element bzgl. der Maximums-Bildung?? Es bleibt spannend ...