Wenn du jemals mit Template-Metaprogrammierung in C++ in Berührung gekommen bist, wirst du mit Erleichterung lesen, dass D einige Werkzeuge bereitstellt, um dir das Leben leichter zu machen. Metaprogrammierung ist eine Technik, die Entscheidungen abhängig von Template-Typeigenschaften ermöglicht und so noch flexiblere Gestaltungsmöglichkeiten für generische Typen bietet.
static if
& is
static if
erlaubt die bedingte Kompilierung eines
Code-Blocks. Im Gegensatz zu if
wird die Bedingung
zur Kompilierzeit ausgewertet:
static if(is(T == int))
writeln("T ist ein int");
static if (is(typeof(x) : int))
writeln("Variable x konvertiert implizit zu int");
Der is
-Ausdruck ist
ein generischer Helfer, der Bedingungen zur Kompilierzeit
auswertet:
static if(is(T == int)) { // T ist Templateparameter
int x = 10;
}
Wenn die Bedingung erfüllt ist, wird der Inhalt des Blocks
kopiert. Die umschließenden Klammern werden weggelassen
und kein weiterer Scope erstellt.
Ein neuer Block / Scope kann allerdings explizit mit { {
und } }
erzeugt werden.
static if
kann überall im Code genutzt werden - in
Funktionen, im globalen Scope sowie in Typdefinitionen.
mixin template
Überall, wo Textbausteine gefragt sind, können
mixin template
s genutzt werden:
mixin template Foo(T) {
T foo;
}
...
mixin Foo!int; // int foo ab hier verfügbar.
mixin template
können eine beliebige Anzahl an komplexen
Ausdrücken enthalten und werden am Instanziierungspunkt
eingesetzt.
Dies macht einen Präprozessor, wie ihn z.B. C und C++
besitzen, überfüssig.
Ein Template kann mit beliebig vielen Beschränkungen (engl.: contraints) definiert werden, um so Eigenschaften eines Typs erzwingen:
void foo(T)(T value)
if (is(T : int)) { // foo!T nur gültig wenn T
// zu int konvertiert
}
Beschränkungen können in booleschen Ausdrücken kombiniert
werden und sogar Funktionsaufrufe enthalten, sofern diese
zur Kompilierzeit ausgwwertet werden können.
Z.B. prüft std.range.primitives.isRandomAccessRange
,
ob ein Typ eine Range ist, die den []
-Operator unterst