opDispatchとopApply

Dは+-のようなオペレータ、 またはクラスと構造体 の呼び出しオペレータ()をオーバーライドできます。 2つの特殊なオペレータオーバーロードopDispatch またはopApplyを詳しく紹介していきます。

opDispatch

opDispatchstructまたはclass、どちらかの型の メンバ関数として定義できます。その型への不明なメンバ関数呼び出しは opDispatchに渡され、不明なメンバ関数の名前がstring テンプレートパラメータとして渡されます。opDispatch包括的 メンバ関数であり、ジェネリックプログラミングの別のレベルを 可能にします - 完璧にコンパイル時に!

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);
l.callB("ABC");

opApply

ユーザ定義レンジを定義する代わりのforeach走査を実装する 手段が、opApplyメンバ関数の実装です。そのような型のforeachによる反復処理は、 パラメータとしての特殊なデリゲートとともにopApplyを呼びます:

class Tree {
    Tree lhs;
    Tree rhs;
    int opApply(int delegate(Tree) dg) {
        if (lhs && lhs.opApply(dg)) return 1;
        if (dg(this)) return 1;
        if (rhs && rhs.opApply(dg)) return 1;
        return 0;
    }
}
Tree tree = new Tree;
foreach(node; tree) {
    ...
}

コンパイラはforeachの本文をオブジェクトが渡される特殊なデリゲートに変形させます。 その唯一無二のパラメータは現在の反復処理の値を含みます。魔法の返値intは解釈される必要があり、 それが0でないとき反復処理を停止させなければなりません。

掘り下げる

rdmd playground.d