opDispatch et opApply

D permet de surcharger des opérateurs comme +, - ou l'opérateur d'appel () pour les classes et les structures. Nous allons nous intéresser à la surcharge des opérateurs opDispatch et opApply.

opDispatch

opDispatch peut être défini comme une méthode d'une struct ou d'une class. Chaque appel à une méthode indéfinie dans cet objet sera passé à opDispatch en passant le nom de la méthode appelée en paramètre de modèle. opDispatch est une méthode attrape-tout qui permet un autre niveau de programmation générique — et le tout à la compilation!

struct C
{
    void callA(int i, int j) { //... }
    void callB(string s) { //... }
}
struct CallLogger(C)
{
    C content;
    void opDispatch(string name, T...)(T vals)
    {
        writeln("called ", name);
        mixin("content." ~ name)(vals);
    }
}

CallLogger!C l;
l.callA(1, 2); // "called content.callA"
l.callB("ABC"); // "called content.callB"

opApply

Au lieu de définir une range, on peut implémenter la méthode opApply pour appeler foreach sur un objet personnalisé. Itérer sur ce genre de type appellera opApply avec un delegate spécial en paramètre:

class Tree
{
    Tree gauche;
    Tree droite;

    int opApply(int delegate(Tree) dg)
    {
        if(gauche && gauche.opApply(dg)) return 1;
        if(dg(this)) return 1;
        if(droite && droite.opApply(dg)) return 1;
        return 0;
    }
    Tree tree = new Tree;
    foreach(node; tree)
    {
        //...
    }
}

Le compilateur transforme le corps du foreach en un delegate() qui est passé à l'objet. Son unique paramètre contiendra le contenu courant de la valeur de l'itération. La valeur de retour int doit être vérifiée et si ce n'est pas 0, l'itération doit être arrêtée.

Pour aller plus loin

rdmd playground.d