Slackで以下のコードが通らないのはなぜ?という話があった。
import std; static assert(isInstanceOf!(Array, Array!char)); // OK! static assert(isInstanceOf!(Regex, Regex!char)); // Compile Error!
どうもこれを調べてみると、alias templatesの場合だとうまくいかないらしい。
public alias Regex(Char) = std.regex.internal.ir.Regex!(Char);
isInstanceOfは内部的にis式を用いているので、こういったことになっている。
struct S1(Char) {} alias S2(Char) = S1!Char; static if (is(S1!char == T3!Args3, alias T3, Args3...)) { static assert(__traits(isSame, T3, S1)); pragma(msg, T3); // S1(Char) static assert(__traits(isTemplate, S1)); static assert(__traits(isTemplate, T3)); pragma(msg, __traits(identifier, T3)); // S1 pragma(msg, T3!char); // S1!char static assert(is(T3!char == S1!char)); static assert(is(Args3[0] == char)); } static if (is(S2!char == T4!Args4, alias T4, Args4...)) { static assert(!__traits(isSame, T4, S2)); pragma(msg, T4); // S1(Char) static assert(__traits(isTemplate, S2)); static assert(__traits(isTemplate, T4)); pragma(msg, __traits(identifier, T4)); // S1: コピペミスではなく、alias templatesの別名参照先の方を指している pragma(msg, T4!char); // S1!char static assert(is(T4!char == S2!char)); static assert(is(Args4[0] == char)); }
現状の言語機能では型のaliasを取るtraitsはあるが、templateのaliasを取る方法は提供されていない。 また、これは言語機能として提供しないと(自分が知る限りでは)取得することはできない。
最初に戻ると、isInstanceOfの実装としてaliasを考慮しないようになっているのはどうなんだ?という気もしてくる。