D allows overriding operators like +
, -
or
the call operator ()
for
classes and structs.
We will have a closer look at the two special
operator overloads opDispatch
and opApply
.
opDispatch
can be defined as a member function of either
struct
or class
types. Any unknown member function call
to that type is passed to opDispatch
,
passing the unknown member function's name as a string
template parameter. opDispatch
is a catch-all
member function and allows another level of generic
programming - completely at compile time!
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");
An alternative way to implementing a foreach
traversal
instead of defining a user defined range is to implement
an opApply
member function. Iterating with foreach
over such a type will call opApply
with a special
delegate as a parameter:
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) {
...
}
The compiler transforms the foreach
body to a special
delegate that is passed to the object. Its one and only
parameter will contain the current
iteration's value. The magic int
return value
must be interpreted and if it is not 0
, the iteration
must be stopped.