インスタンスメソッドのタプル化
構造体やクラスには tupleof プロパティがあるがこれは、フィールドつまりデータメンバに関してのみ取り出せる。しかし function や delegate も型であり値を持つわけだから、インスタンスメソッドや、static メソッドをタプル化することもできる筈である。
TypeInfo typeinfo(T) (T arg){ return typeid(T); } class C { private { int id_; char[] name_; } const int initial_id = 100; const char[] initial_name = "AAA"; this( int id = initial_id, char[] name = initial_name ) { id_ = id; name_ = name.dup; } char[] toString() { return house.string.toString(this.tupleof); } int id() { return id_; } char[] name() { return name_.dup; } } void main() { auto cs = [ new C(0, "A"), new C(1, "B"), new C(2, "C"), ]; writefln(typeinfo(cs)); writefln(cs); } ... doki.decorator.C[3] [(0,A),(1,B),(2,C)]
とまぁ、このような簡単なクラスからメソッドを delegate として取出し、
auto dgs = [ tuple(&cs[0].id, &cs[0].name), tuple(&cs[1].id, &cs[1].name), tuple(&cs[2].id, &cs[2].name), ]; writefln(typeinfo(dgs)); foreach (dg; dgs) { writefln(typeinfo(dg)); writefln(toString(dg.value[0](), dg.value[1]())); } ... std.bind.Tuple!(int delegate(),char[] delegate()).Tuple[3] std.bind.Tuple!(int delegate(),char[] delegate()).Tuple (0,A) std.bind.Tuple!(int delegate(),char[] delegate()).Tuple (1,B) std.bind.Tuple!(int delegate(),char[] delegate()).Tuple (2,C)
タプル化したあと呼び出すというのは、割と簡単にできる。
クラスの外側からだとインスタンスを作ってからできるし、自動型推論も使えるので。
しかしこれ、tupleof プロパティよろしく、クラス自体にそういう機能をつけたいとこである。
class C { ... Tuple!(typeof(&typeof(this).init.id), typeof(&typeof(this).init.name)) methods() { return tuple(&id, &name); } } void main() { auto dg = cs[0].methods(); writefln(typeinfo(dg)); writefln(toString(dg.value[0](), dg.value[1]())); } ... std.bind.Tuple!(int delegate(),char[] delegate()).Tuple (0,A)
ご覧のように短い名前のメソッドがたった2つでかなり長いシグネチャーになってしまった。
メソッドボディの外側だと自動型推論が使えないし、this への参照がままならないので init プロパティに頼らなければいけなかったりするからである。
まぁ、シグネチャーの戻り値部分は事前に alias かけとくとして。
もうちょっとウマい方法ないかと考慮中。