【D言語】テンプレートの遅延インスタンス化
D言語erの皆さん、こんにちは。
今回は、テンプレートの遅延インスタンス化について語ります。
時に、テンプレート引数としてテンプレートをインスタンス化したものを渡す時、その場でインスタンス化されてほしくない時があります。 例としては、std.traits.Selectを使う場合が挙げられます。
import std.traits;
template T1(T){
pragma(msg, "T1");
alias T T1;
}
template T2(T){
pragma(msg, "T2");
alias T T2;
}
pragma(msg, Select!(true, T1!int, T2!long));
void main(){}
このコードの出力は、
T1
T2
int
となります。 全くインスタンス化される必要のないT2がインスタンス化されています。 これを何とかします。
無名テンプレートがあれば、それを使って解決できます。 しかし、実際には無いのでその他の方法で頑張ります。 今回は、文字列mixinを使ったLazyテンプレートを使って、インスタンス化を遅延させます。
template Select(bool cond, alias T, alias F){
static if(cond) alias T!() Select; else alias F!() Select;
}
template Lazy(string src){
template Lazy(){
mixin("alias " ~ src ~ " Lazy;");
}
}
template T1(T){
pragma(msg, "T1");
alias T T1;
}
template T2(T){
pragma(msg, "T2");
alias T T2;
}
pragma(msg, Select!(true, Lazy!q{ T1!int }, Lazy!q{ T2!long }));
pragma(msg, Select!(false, Lazy!q{ T1!int }, Lazy!q{ T2!long }));
void main(){}
このコードの出力は、
T1
int
T2
long
ちゃんとインスタンス化が遅延されています!!
この文字列mixinを使う方法ですが、いくつか問題があります。
- 文字列mixinを使っているので、文字列内のシンボルがLazyテンプレートから見えなきゃいけない。
- 文字列mixinを使っているので、コンパイルが少し遅くなる気がする。
- 遅延インスタンス化されたものを受け取る側も、それを考慮する必要がある。
この方法はあまり汎用的には使えませんが、必要になった時に使ってみてください。