インスタンスメソッドのタプル化

構造体やクラスには 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 かけとくとして。

もうちょっとウマい方法ないかと考慮中。