Dは+
、-
のようなオペレータ、
またはクラスと構造体
の呼び出しオペレータ()
をオーバーライドできます。
2つの特殊なオペレータオーバーロードopDispatch
またはopApply
を詳しく紹介していきます。
opDispatch
はstruct
または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");
ユーザ定義レンジを定義する代わりの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
でないとき反復処理を停止させなければなりません。