ReturnTypeテンプレートのファンクタ対応
一瞬恥ずかしい日記があった気がしますが気のせいです。
std.traitsのReturnTypeテンプレートは、opCallを実装したファンクタには対応していません。適当に対応させてみます。
template MyReturnType(alias dg){ static if (is(typeof(dg) R == return)){ alias R MyReturnType; } else static if (is(typeof(dg.opCall) T)){ static if (is(T R == return)){ alias R MyReturnType; } } else { static assert(0); } } template MyReturnType(dg){ static if (is(dg R == return)){ alias R MyReturnType; } else static if (is(dg.opCall T)){ static if (is(T R == return)){ alias R MyReturnType; } } else { static assert(0); } }
ここで「あれ?std.traitsみたく…」
template MyReturnType(alias dg){ alias MyReturnType!(typeof(dg)) MyReturnType; }
「…ってすればいいんじゃないの?」と思った人。あなたは賢い、ですが正しくはありません。現実は厳しいのです!
どういうことかというと、ファンクタを渡した途端に「再帰的なaliasです!」と叱られてしまうのでした。
まあそんなはずはないわけですが、コンパイラがそう言ったんだからきっとそうなんだろうよ!ぺっ!
追記:Dスレ10で、同じ働きのもっとシンプルな物を発見したのだった。
更に追記:折角なので全部書いておいた
template MyReturnType(alias dg){ static if (is(typeof(dg.opCall) T)){ alias ReturnType!(T) MyReturnType; } else { alias ReturnType!(dg) MyReturnType; } } template MyReturnType(dg){ static if (is(dg.opCall T)){ alias ReturnType!(T) MyReturnType; } else { alias ReturnType!(dg) MyReturnType; } } template MyParameterTypeTuple(alias dg){ static if (is(typeof(dg.opCall) T)){ alias ParameterTypeTuple!(T) MyParameterTypeTuple; } else { alias ParameterTypeTuple!(dg) MyParameterTypeTuple; } } template MyParameterTypeTuple(dg){ static if (is(dg.opCall T)){ alias ParameterTypeTuple!(T) MyParameterTypeTuple; } else { alias ParameterTypeTuple!(dg) MyParameterTypeTuple; } }