【D言語】__LINE__と__FILE__のバグっぽい挙動

coi loi pilno lo dy. zei bangu

dmd v2.060は、template引数のデフォルト値で使われるLINEFILEについてバグっぽい挙動をします。 その辺について語っていきます。


期待される挙動

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__は無意味?

実はそうでもありません。 なぜか、テンプレート引数を明示的に与えない関数テンプレートの場合、LINEFILEは仕様通りに動作します。


size_t func(size_t line = __LINE__)(){
    return line;
}
static assert(func() == 4);
void main(){}

このコードはコンパイルが通ります。


バグか仕様か

実はこのバグのような挙動、Bugzillaでずいぶん前に報告されています。 dmdの実装を見たわけではないので確かなことは言えませんが、これほど放置されているということは、もしかすると仕様なのかもしれません。


まとめ

とりあえず、バグであることを、そして修正されることを祈ります。 LINEFILEを上記のように使いたいという方は、関数テンプレートを活用するといいかもしれません。

次:http://codelogy.org/?p=960

担当:美馬(ロジバンすっごく面白い)