// released into the public domain import std.stdio; class A {} class B : A {} class C : A {} class Dispatcher { void foo(A a) { writefln("A"); } void foo(B b) { writefln("B"); } mixin Dispatch!("foo"); } class ExDispatcher : Dispatcher { alias Dispatcher.foo foo; override void foo(B b) { writefln("B override"); } void foo(C c) { writefln("C"); } mixin Dispatch!("foo"); } void main() { auto disp = new Dispatcher; disp.dispatch(new A); // calls disp.foo(A) disp.dispatch(new B); // calls disp.foo(B) Dispatcher exdisp = new ExDispatcher; exdisp.dispatch(new A); // calls disp.foo(A) exdisp.dispatch(new B); // calls exdisp.foo(B) exdisp.dispatch(new C); // calls exdisp.foo(C) } class MethodNotFoundException : Exception { this(string msg) { super(msg); } } template Dispatch(string fname) { mixin("alias typeof(" ~ fname ~ ") fsym;"); static if(is(fsym arg_types == function) && is(fsym return_type == return)) { return_type dispatch(Object o, arg_types[1..$] params) { alias typeof(__traits(getVirtualFunctions, typeof(this), fname)) funcs; foreach(i, func; funcs) { static if(is(func it_arg_types == function) && is(func it_return_type == return)) { static assert(is(arg_types[1..$] == it_arg_types[1..$]) && is(return_type == it_return_type), "Except for the first argument, the signature of all functions must be identical."); static assert(is(it_arg_types[0] == class), "First argument must be a class type."); if(it_arg_types[0].classinfo is o.classinfo) return __traits(getVirtualFunctions, this, fname)[i](cast(it_arg_types[0]) o, params); } else static assert(false, fname ~ " is not a function"); } throw new MethodNotFoundException("No matching method '" ~ fname ~ "' found in " ~ this.classinfo.name ~ " for class " ~ o.classinfo.name); } } else static assert(false, fname ~ " is not a function"); }