gdc の ABI が違ったのでその対応とか入れてみました。 Linux の DMD-0.159 と gdc-0.18 、 WINE の DMD-0.159 で確認。
import std.stdio;
template mem_fun(T) {
T (*mem_fun(T (*f)()))(Object) {
return cast(T (*)(Object))f;
}
}
version (GNU) {
template mem_fun(T, U) {
T (*mem_fun(T (*f)(U)))(Object, U) {
return cast(T (*)(Object, U))f;
}
}
} else {
class mem_fun_t(T, U) {
T (*fp)(U, Object);
this(T (*f)(U, Object)) {
fp = f;
}
T opCall(Object o, U u) {
return fp(u, o);
}
}
template mem_fun(T, U) {
mem_fun_t!(T, U) mem_fun(T (*f)(U)) {
return new mem_fun_t!(T, U)(cast(T (*)(U, Object))f);
}
}
}
class C {
int val_;
this(int val) { val_ = val; }
int func() {
return val_;
}
int func2(int x) {
return val_+x;
}
}
int main() {
auto mf = mem_fun(&C.func);
auto mf2 = mem_fun(&C.func2);
C c1 = new C(1);
C c2 = new C(2);
writefln(mf(c1)); // 1
writefln(mf(c2)); // 2
writefln(mf2(c1, 3)); // 4
writefln(mf2(c2, 4)); // 6
return 0;
}何してるかって要はキャストしてるだけなのでインチキ。関数なんて呼べりゃいいんです。
0引数mem_funは本当にキャストしてるだけです。関数ポインタ取って関数ポインタ返す関数なのでシグネチャがややこしいですが。
1引数mem_funは引数順をmem_fun_tでひっくり返してます。thisはレジスタ渡しなので普通の関数の最終引数と同じ扱いぽいです。 gdc の場合はひっくり返す必要無し。