D erlaubt es, Operatoren wie +
, -
oder den Aufrufoperator
()
für Klassen und Strukturen
zu überladen.
Im Folgenden werden die beiden speziellen Operatorüberladungen
opDispatch
und opApply
genauer beleuchtet.
opDispatch
kann als Memberfunktionen eines struct
-
oder class
-Typs definiert werden. Jede unbekannte Memberfunktionsaufruf
für diesen Typ wird an opDispatch
weitergeleitet,
wobei sowohl Name als auch Parameter der unbekannten
Funktion als string
durchgereicht werden.
Damit ist opDispatch
eine alles auffangede Memberfunktion
und erlaubt eine andere Ebene der Generischen Programmierung,
und das komplett zur Kompilierzeit!
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");
Eine alternative Implementing eines foreach
-Durchlaufs,
verglichen mit der Definition einer benuterdefinierten Range,
ist die Erstellung einer opApply
-Memberfunktion.
Das Iterieren mit foreach
oder ähnlichem wird ein
spezielles Delegate als Parameter aufrufen:
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) {
...
}
Der Compiler wandelt den foreach
-Rumpf in ein spezielles
Delegate um, dass an das Objekt übergeben wird. Sein einziger
Parameter ist jeweils der aktuelle Wert der Iteration.
Der magische int
-Rückgabewert muss interpretiert werden und,
falls dieser nicht 0
ist, die Iteration abgebrochen werden.