for_each() die Vierte

Bauen wir also nun statt der Funktion showInt() ein Funktionstemplate showIt() ...

template <typename T>
void showIt(const T& value)
{cout << value << " ";}
... und setzen den Namen des Templates inklusive Typparameter in den Aufruf von for_each() ein.
template <typename T>
void showVectorContent(const vector<T>& v)
{
 for_each(v.begin(),v.end(),showIt<T>);
}
Soweit erscheint das folgerichtig - aber der Compiler liefert uns leider eine wenig informative Fehlermeldung. Nun mögen Sie experimentieren mit kleinen syntaktischen Änderungen wie showIt<T>() oder Ähnlichem. Es bringt nichts.

Warum geht das nicht?
Der Parameter showIt<T> ist nicht verwendbar, weil es keine Instanz des Funktionstemplates gibt.

Wir erinnern uns an den Absatz im Buch von Kuhlins und Schader "Die C++ Standardbibliothek", 2. Auflage, Springer-Verlag:

Versuchen wir es also zuerst mit dem vielleicht Einfacheren, mit einem Zeiger auf eine Funktion ||:-|
Ich zeig's Ihnen einfach 'mal:

  1. Was liefert eine nach diesem Template gebildete Funktion? Nichts! - also void

  2. Wie sieht die Parameterliste der Funktion aus? (const T&)

  3. Nun erinnern Sie sich an die Typangabe eines Datenfeldes (Array)!
    double Zahlen[10]; // Zahlen ist ein Exemplar (Instanz) des Datenfeldtyps double [10].

    Entsprechend zerrissen ist die Typangabe für eine Funktion:
    void f(const T&); // f ist eine Instanz des Funktionstyps void (const T&).

    Nun brauchen wir aber einen Zeiger auf eine Funktion diesen Typs: void *f (const T&);
    So erhalten wir keinen Zeiger, weil der Dereferenzierungsoperator * an void gebunden wird. void* ist als Resultatstyp ein typenloser Zeiger und f bleibt eine Funktion. Also klammern wir * mit f zusammen: void (*f) (const T&);

    Jetzt müssen wir diesem Zeiger f nur noch die Startadresse der Funktion zuweisen:
    void (*f)(const T&) = showIt<T>;
    T ist der Typparameter des Funktionstemplates showVectorContent.
    f beinhaltet nun die Startadresse einer Instanz des Funktionstemplates mit dem Parametertyp T, was in unserem Falle int ist. Der Compiler legt diese Instanz automatisch an, weil Bedarf besteht. Den Zeiger f können wir als dritten Parameter an for_each übergeben.

Das Ergebnis unserer ausgedehnten Bemühungen sieht wie folgt aus:

template <typename T>
void showIt(const T& value)
{cout << value << " ";}

template <typename T>
void showVectorContent(const vector<T>& v)
{
 void (*f)(const T&) = showIt<T>;
 for_each(v.begin(),v.end(),f);
}
So funktioniert es und erhält uns die Freiheiten von Templates.
Auf der nächsten Seite gehen wir ein Funktionsobjekt an.