|
|
||
書こう書こうと思っていたんですがすっかり忘れていました。何を書こうとしていたかさえ忘れてたんですが何とか思い出しました。
今までDではできないできないと散々言ってきたクラステンプレートに対する特殊化ですが、stringofプロパティを使うことで解決します。
とりあえずクラステンプレートに対する特殊化って何?という人のために例をC++のコードで。
template <typename T> class Hoge{}; template <typename T> class Hige{}; // プライマリテンプレート template <typename U> class Hige< Hoge<U> >{}; // 任意の型引数を取るクラステンプレートHogeに対する特殊化
Dではこの「任意の型引数を取るクラステンプレートHogeに対する特殊化」が出来なかったわけです(長い)。
試しに普通の方法で書こうとしてみても…
class Hoge(T){} class Hige(T){} class Hige(Hoge!(T)){} // 文法エラー class Hige(T){ static if(is(T == Hoge)){} else {} // エラー }
static if を使った二番目の例がエラーになる理由は、「class Hoge(T){}」が実際のところは「template Hoge(T){class Hoge{}}」の単なる構文糖に過ぎないため、Hogeが型でなくテンプレート名として解釈されるためです(Hoge.Hogeとかしても勿論ダメ)。
で、まあこれが出来るようになったという話。
class Hige(T){ static if(T.stringof == "Hoge"){} else {} }
すごいダサイですけど。ちゃんと動きます。
ただこの方法でもTがクラステンプレートHogeだということはわかっても、何を引数として取っているかまでは分からないという問題は残されたままです。
Dの言語仕様には、コンパイル時にクラステンプレートの型から引数を知る方法はありません。
実行時はどうかというと、知る方法は「一応」ありますが…完全修飾名から得るしかないので実の泥臭い感じです。
まあ型引数知りたい時はtraits(std.traitsのことではない)でなんとかしろってこった!
しかし相変わらず対象読者の分からない文章ばかり書いてます。何か普通の書こうかなあ。
class Hoge(T){}
private T isHoge(T)(Hoge!(T)*x);
class Hige(T){
static if(is(typeof(isHoge((T*).init)) x)){
pragma(msg,x.stringof);
}else{
pragma(msg,T.stringof);
}
}
class Hoge(T){}
class Hige(T){
static if(is(T t:Hoge!(t))){
pragma(msg,t.stringof);
}else{
pragma(msg,T.stringof);
}
}