template <class typ> /* Deklaration */ typ min(typ a, typ b); ... template <class argtype> /* Definition */ argtype min(argtype a, argtype b) { return (a<b)?a:b; }
Funktionsschablonen deklarieren/defininieren noch keine Funktionen. Dies geschieht erst, wenn im Programm zur Schablone passende Deklarationen oder Anwendungen auftreten:
int min(int, int); int main() { double f = 99; // min(double, double) cout << min(8.7, f); int i; // min(int*, int*) cout << min(&i, (int*) &f); }
Der Compiler hat die Aufgabe, für jede benötigte Ausprägung der Funktion Code zu erzeugen. In unserem Beispiel sind das zwei Versionen von min().
CC generiert:
_min__Fdd // double, double _min__FPiPi // int*, int*
Das Problem ist nun, daß Anwendungsstelle und Funktionsschablonendefinition i.A. nicht in der gleichen Datei liegen (getrennte Übersetzung).
Der Compiler kennt bei der Übersetzung der Schablonenanwendung deren Definition nicht und kann daher nicht den Code für benötigte Version erzeugen.
Dies geht erst zur Linkzeit, wenn alle Programmkomponenten zusammen kommen.
Zur Zeit erwarten viele Compiler, daß die Schablonendefinition an
der Anwendungstelle verfügbar ist (z.B. über #include
).
Der Normentwurf (Dezember 1996) schlägt eine Kennzeichnung von
Schablonen
mit export
vor. Exportierte Schablonen brauchen an der
Anwendungsstelle nur noch deklariert zu werden.
.
Für die Benutzung von Funktionsschablonen gelten folgende Bedingungen:
Beispiel:
int i; unsigned int j; cout << min(i,j); // Fehler: min braucht 2 gleiche Typen
Beispiel:
template <const X&x, int i> void f() { ... }
Beispiel:
template <class c1, class c2> c1 min(c1 a, c2 b, char *text);
Auch für diese Parameter: keine automatische Konvertierung.
Beispiel:
template <class c1> c1 min(c1 a, c1 b); int i,j; float k; i = min(i,j); /* int-minimum */ k = min(i,j); /* int-minimum */
template <class c> inline int check(c arg);
Beispiel:
template <class c> c fu (c arg1, double d); template <class c> c fu (double d, c arg1); template <class c> int fu (c arg1, double d); // FEHLER
Beispiel:
template <class c> c min(c arg1, c arg2) { return (a<b)?a:b; } // die Schablone ist fuer strings nicht gut: // also: char* min(char* a, char* b) { return (strcmp(a,b) < 0)? a : b; }
Liegen Schablonen- und konkrete Versionen einer Funktion vor, entscheidet der Compiler wie folgt:
Beispiel:
template <class c> c fu(c,c); // Schablone char* fu(char*, char*) // konkrete Fkt.1 int fu(int, int) // konkrete Fkt.2 fu("x","y"); // konkrete Fkt.1 fu(4,7); // konkrete Fkt.2 fu(3.4, 5.6); // Schablone(double) fu(4,6.0); // konrete Fkt. 2