@ C++er各位 ideone.com/6ElBKy clang C++11 mode
— pepshiso (@pepshiso) May 5, 2013
clang のバグっぽいけど調査中
— pepshiso (@pepshiso) May 5, 2013
以下のコードがclangでコンパイルエラーになる。
template <class T> void g() { T x(0); } template <class T> void f() { struct local { local(int) {} }; g<local>(); } int main() { f<void>(); }
エラーの内容は、g<local>で、適合するlocalのコンストラクターが見つからないというものだ。たしかにlocalにはint型をひとつ取るコンストラクターがあるというのに。
どうやらこれは、テンプレート(関数テンプレートやクラステンプレートのメンバー関数)内のローカルクラスを明示的テンプレート実引数指定すると、ローカルクラスのユーザー定義コンストラクターのlookupが失敗するというバグのようだ。
template < typename T > struct S { T t ; S() : t(0) { } } ; // local class defined inside template difinition. template < typename T > void f() { struct local { local( int ) { } } ; S<local> s ; } // local class defined inside non-template difiniton. void g() { struct local { local( int ) { } } ; S<local> s ; } int main() { f<void>() ; // error: no matching constructor for initialization of 'local' g() ; // OK, lookup works }
テンプレート定義内で定義されていないローカルの場合は起こらない。
関数テンプレートの場合、明示的テンプレート実引数指定を使った場合だけ、この問題に引っかかる。
template < typename T > void f( ) { T x(0) ; } template < typename T > void call_f_template() { struct local { local(int) {} } ; f<local>() ; } void call_f() { struct local { local(int) {} } ; f<local>() ; }int main() { call_f_template<void>() ; // error: no matching constructor for initialization of 'local' call_f() ; }
Argument Deductionが使える文脈ではエラーにならない。そのような文脈では、たとえexplicit template argument specificationを使ったとしても問題なく動く。
template < typename T > void f( T const & ) { T x(0) ; } template < typename T > void call_f_template() { struct local { local(int) {} } ; local obj(0) ; f( obj ) ; // OK f<local>( obj ) ; // Also OK } int main() { call_f_template<void>() ; }
実に不思議なバグだ。はじめてclangのC++11フロントエンドのバグを目にした。
というわけでバグ報告してみた。
追記:すでに重複報告だった。しかも2011年から既知のバグだ。当時はコンパイラーがクラッシュするバグだったらしい。
Bug 9685 – Crash on using local struct in function template as template parameter
No comments:
Post a Comment