【D言語】__LINE__と__FILE__のバグっぽい挙動
coi loi pilno lo dy. zei bangu
dmd v2.060は、template引数のデフォルト値で使われるLINEとFILEについてバグっぽい挙動をします。 その辺について語っていきます。
期待される挙動
D言語の言語仕様のTemplateValueParameterには、
__FILE__ と __LINE__ は、 テンプレートがインスタンス化された場所のファイル名と行番号に展開されます。
とあります。
ということは、
template T(size_t line = __LINE__){
enum T = line;
}
static assert(T!() == 4);
のコンパイルが通るはずです・・・
実際の挙動
が、通りません。というか、通ったらこんな記事書きません。 具体的に言うと、以下の様なエラーが出ます。
Error: static assert (1LU == 4LU) is false
T!()が1であるということは、つまりLINEがインスタンス化された場所の行数ではなく、定義されている場所の行数に展開されています。 FILEでも同様のことが起きます。
もしかして、__LINE__と__FILE__は無意味?
実はそうでもありません。 なぜか、テンプレート引数を明示的に与えない関数テンプレートの場合、LINEとFILEは仕様通りに動作します。
size_t func(size_t line = __LINE__)(){
return line;
}
static assert(func() == 4);
void main(){}
このコードはコンパイルが通ります。
バグか仕様か
実はこのバグのような挙動、Bugzillaでずいぶん前に報告されています。 dmdの実装を見たわけではないので確かなことは言えませんが、これほど放置されているということは、もしかすると仕様なのかもしれません。
まとめ
とりあえず、バグであることを、そして修正されることを祈ります。 LINEとFILEを上記のように使いたいという方は、関数テンプレートを活用するといいかもしれません。
担当:美馬(ロジバンすっごく面白い)