Template-Metaprogrammierung

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 templates 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.

Template-Beschränkungen

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

Weiterführende Quellen

Grundlegende Verweise

Fortgeschrittene Verweise

rdmd playground.d