Méta-programmation par modèles

Si vous avez déjà eu à faire de la méta-programmation par modèles en C++, vous serez soulagés d'apprendre que le D offre des outils pour vous rendre la vie plus facile. La méta-programmation par modèles est une technique qui permet de prendre des décisions en fonction de certaines propriétés des types, et donc de rendre des types génériques encore plus flexibles.

static if et is

Comme le if normal, static if compile un bloc de code en fonction d'une condition qui peut être évaluée à la compilation:

static if(is(T == int))
{
    writeln("T est un entier");
}
static if(is(typeof(x) : int))
{
    writeln("T se convertit implicitement en entier");
}

L'expression is est un outil générique qui évalue des conditions à la compilation.

static if(is(T == int)) // T est un paramètre de modèle
{
    int x = 10;
}

Les accolades sont optionelles si la condition est valide et aucune nouvelle portée n'est créée. Pour créer un nouveau bloc à la compilation, utiliser { { et } }.

static if peut être utilisé n'importe où dans le code, dans des fonctions, dans la portée globale ou dans des définitions de types.

Modèle de mixin

À chaque fois que vous voyez de la duplication de code, les modèles de mixin sont vos amis:

mixin template Foo(T)
{
    T foo;
}
...
mixin Foo!int; // la variable foo de type entier est accessible à partir d'ici

Un modèle de mixin peut contenir n'importe quel nombre d'expressions complexes, qui sont insérées dans le code à l'endroit de l'instanciation du modèle. Dites au revoir au pré-processeur si vous venez de C!

Contraintes de modèles

Un modèle peut être défini avec n'importe quel nombre de contraintes qui garantissent certaines propriétés que les types doivent avoir:

void foo(T)(T value)
if (is(T : int))
{
    // foo!T ne peut être valide
    // que si T peut se convertir
    // en entier
}

Les contraintes peuvent être combinées pour former une expression booléenne, et peuvent même contenir des appels à des fonctions qui peuvent être appelées à la compilation (CTFE). Par exemple, std.range.primitives.isRandomAccessRange vérifie qu'un type est bien une range et supporte l'opérateur []

Pour aller plus loin

Références de base

Ressources avancées

rdmd playground.d