import std.stdio;
import std.traits;
struct WM {
size_t value;
}
bool hasWMAttr(alias T)(WM wm) {
foreach(attr; __traits(getAttributes, T)) {
static if(is(typeof(attr) == WM))
if(attr == wm) return true;
}
return false;
}
mixin template Dispatcher()
{
void dispatch(T)(T msg)
if(hasMember!(T, "message") && is(typeof(T.message) == size_t))
{
alias void delegate(T msg) DG;
foreach(m; __traits(derivedMembers, typeof(this))) {
foreach(func; __traits(getOverloads, typeof(this), m)) {
static if(is(ParameterTypeTuple!(typeof(func)) == ParameterTypeTuple!(DG))) {
if(hasWMAttr!func(WM(msg.message))) {
func(msg);
}
}
}
}
}
}
// Sample
struct Message {
size_t message;
// wparam, lparam...
}
class Test {
mixin Dispatcher;
[WM(10)]
void wm10(Message msg) {
writeln("Received message10");
}
[WM(20)]
void wm20(Message msg) {
writeln("Received message20");
}
//[WM(10), WM(20)]
@WM(10) @WM(20)
void wm(Message msg) {
writeln("Received message: ", msg.message);
}
/+
// Linker error
@WM(100)
void wm(Message msg) { }
+/
}
void main()
{
auto test = new Test();
test.dispatch(Message(10));
test.dispatch(Message(20));
}
aW1wb3J0IHN0ZC5zdGRpbzsKaW1wb3J0IHN0ZC50cmFpdHM7CgpzdHJ1Y3QgV00gewogIHNpemVfdCB2YWx1ZTsKfQoKYm9vbCBoYXNXTUF0dHIoYWxpYXMgVCkoV00gd20pIHsKICBmb3JlYWNoKGF0dHI7IF9fdHJhaXRzKGdldEF0dHJpYnV0ZXMsIFQpKSB7CiAgICBzdGF0aWMgaWYoaXModHlwZW9mKGF0dHIpID09IFdNKSkKICAgICAgaWYoYXR0ciA9PSB3bSkgcmV0dXJuIHRydWU7CiAgfQogIHJldHVybiBmYWxzZTsKfQoKbWl4aW4gdGVtcGxhdGUgRGlzcGF0Y2hlcigpCnsKICB2b2lkIGRpc3BhdGNoKFQpKFQgbXNnKQogIGlmKGhhc01lbWJlciEoVCwgIm1lc3NhZ2UiKSAmJiBpcyh0eXBlb2YoVC5tZXNzYWdlKSA9PSBzaXplX3QpKQogIHsKICAgIGFsaWFzIHZvaWQgZGVsZWdhdGUoVCBtc2cpIERHOwogICAgZm9yZWFjaChtOyBfX3RyYWl0cyhkZXJpdmVkTWVtYmVycywgdHlwZW9mKHRoaXMpKSkgewogICAgICBmb3JlYWNoKGZ1bmM7IF9fdHJhaXRzKGdldE92ZXJsb2FkcywgdHlwZW9mKHRoaXMpLCBtKSkgewogICAgICAgIHN0YXRpYyBpZihpcyhQYXJhbWV0ZXJUeXBlVHVwbGUhKHR5cGVvZihmdW5jKSkgPT0gUGFyYW1ldGVyVHlwZVR1cGxlIShERykpKSB7CiAgICAgICAgICBpZihoYXNXTUF0dHIhZnVuYyhXTShtc2cubWVzc2FnZSkpKSB7CiAgICAgICAgICAgIGZ1bmMobXNnKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9Cn0KCi8vIFNhbXBsZQoKc3RydWN0IE1lc3NhZ2UgewogIHNpemVfdCBtZXNzYWdlOwogIC8vIHdwYXJhbSwgbHBhcmFtLi4uCn0KCmNsYXNzIFRlc3QgewogIG1peGluIERpc3BhdGNoZXI7CiAgW1dNKDEwKV0KICB2b2lkIHdtMTAoTWVzc2FnZSBtc2cpIHsKICAgIHdyaXRlbG4oIlJlY2VpdmVkIG1lc3NhZ2UxMCIpOwogIH0KICBbV00oMjApXQogIHZvaWQgd20yMChNZXNzYWdlIG1zZykgewogICAgd3JpdGVsbigiUmVjZWl2ZWQgbWVzc2FnZTIwIik7CiAgfQogIC8vW1dNKDEwKSwgV00oMjApXQogIEBXTSgxMCkgQFdNKDIwKQogIHZvaWQgd20oTWVzc2FnZSBtc2cpIHsKICAgIHdyaXRlbG4oIlJlY2VpdmVkIG1lc3NhZ2U6ICIsIG1zZy5tZXNzYWdlKTsKICB9CiAgLysKICAvLyBMaW5rZXIgZXJyb3IKICBAV00oMTAwKQogIHZvaWQgd20oTWVzc2FnZSBtc2cpIHsgfQogICsvCn0KCnZvaWQgbWFpbigpCnsKICBhdXRvIHRlc3QgPSBuZXcgVGVzdCgpOwogIHRlc3QuZGlzcGF0Y2goTWVzc2FnZSgxMCkpOwogIHRlc3QuZGlzcGF0Y2goTWVzc2FnZSgyMCkpOwp9