マクロの代わり
class TypeAndId2Type(T, uint id) { } template message_handler(_T, uint _id, alias _handler) { enum { id = _id } alias _T T; bit dispatch_handler(Message m, TypeAndId2Type!(T, _id) dummy) { if(m.id == _id){ _handler(m); return true; }else{ return false; } } } template message_handler(_T, uint _id, alias _handler, alias _next) { enum { id = _id } alias _T T; bit dispatch_handler(Message m, TypeAndId2Type!(T, _id) dummy) { if(m.id == _id){ _handler(m); return true; }else{ TypeAndId2Type!(_next.T, _next.id) dummy; return _next.dispatch_handler(m, dummy); } } } template message_dispatcher(alias _list) { void dispatch(Message m) { TypeAndId2Type!(_list.T, _list.id) dummy; if(!_list.dispatch_handler(m, dummy)){ on_default(m); } } } template message_inheriter(alias _list) { private final void inherit(Message m) { TypeAndId2Type!(_list.T, _list.id) dummy; if(!_list.dispatch_handler(m, dummy)){ on_default(m); } } } const uint create_id = 10; const uint destroy_id = 11; class Message { uint id, w, l, result; } class Window { private final void on_create(Message m) { printf("Window.on_create\n"); } private final void on_destroy(Message m) { printf("Window.on_destroy\n"); } void on_default(Message m) { printf("Window.on_default %d\n", m.id); } mixin message_handler!(Window, create_id, on_create) create_handler; mixin message_handler!(Window, destroy_id, on_destroy, create_handler) destroy_handler; mixin message_dispatcher!(destroy_handler) dispatcher; alias destroy_handler window_handler_list; } class Button : Window { private final void on_create(Message m) { printf("Button.on_create\n"); inheriter.inherit(m); } mixin message_handler!(Button, create_id, on_create, window_handler_list) create_handler; mixin message_dispatcher!(create_handler) dispatcher; alias create_handler button_handler_list; mixin message_inheriter!(window_handler_list) inheriter; } class CheckBox : Button { private final void on_destroy(Message m) { printf("CheckBox.on_destroy\n"); inheriter.inherit(m); } mixin message_handler!(CheckBox, destroy_id, on_destroy, button_handler_list) destroy_handler; mixin message_dispatcher!(destroy_handler) dispatcher; alias destroy_handler checkbox_handler_list; mixin message_inheriter!(button_handler_list) inheriter; } void main() { CheckBox c = new CheckBox; Message m = new Message; m.id = create_id; c.dispatch(m); m.id = destroy_id; c.dispatch(m); }
わかったこと。
- template中でsuper使うとdmdが落ちる
- class中のmixinのalias引数にfunctionやdelegateリテラルを渡せない
- privateにするとoverrideを免れることができる
- alias引数でメソッドを渡す場合、template側ではレシーバが選べない(暗黙のthisのみ)
マクロの代わりとしてはいまいち力不足な気がします。無いよりまし。templateまわりでdmdがよく落ちるのは相変わらず。
mixinのサンプルがあまり出てきてないのは、dmdがバグバグなせいなのか、それとも私がテンションを盛り下げるような事を書いたせいなのか…。