D erlaubt die Defintion von Funktionstemplates wie C++ und Java. Dies ist ein Mittel um generische Funktionen oder Objekte zu definieren, die für jeden Typ funktionieren, der mit den Anweisungen des Funktionsrumpfs kompiliert:
auto add(T)(T lhs, T rhs) {
return lhs + rhs;
}
Der Template-Parameter T
wird in runden Klammern vor den eigentlichen
Funktionsparametern definiert. T
ist ein Platzhalter, der vom Compiler
ersetzt wird, wenn die Funktion tatsächlich mit dem !
-Operator
instanziiert wird:
add!int(5, 10);
add!float(5.0f, 10.0f);
add!Animal(dog, cat); // kompiliert nicht! Animal implementiert + nicht
Funktionstemplates haben zwei Parametersätze - den ersten für Kompilierzeit-Argumente und den zweiten für Laufzeit-Argumente. (Normale Funktionen akzeptieren nur Laufzeit-Argumente). Wenn ein oder mehrere Kompilierzeit-Argumente beim Aufruf ausgelassen werden, versucht der Compiler deren Typ aus der Liste der Laufzeit- Argumente abzuleiten.
int a = 5; int b = 10;
add(a, b); // T wird abgeleitet zu `int`
float c = 5.0;
add(a, c); // T wird abgeleitet zu `float`
Eine Funktion kann beliebig viele Template-Parameter besitzen, welche
während der Instanziierung mit der func!(T1, T2 ..)
-Syntax spezifiziert
werden. Template-Parameter können von jedem Basistyp sein (inkl. string
und Fließkommatypen).
Anders als Generics in Java, beziehen sich Templates in D nur auf die Kompilierzeit. Dies führt zu hochoptimiertem Code maßgeschneidert für die beim Funktionsaufruf genutzten Typen.
Natürlich können auch die Typen struct
, class
und interface
als Template
definiert werden.
struct S(T) {
// ...
}