関連: http://d.hatena.ne.jp/gintenlabo/20110413/1302675301
C++0x の関数テンプレートがデフォルトテンプレート引数を取れるようになったことで可能になった,
extern void* enabler; template < typename T, typename std::enable_if< std::is_arithmetic<T>::value >::type*& = enabler > void f( T ) { std::cout << "T is arithmetic" << std::endl; } template < typename T, typename std::enable_if< std::is_pointer<T>::value >::type*& = enabler > void f( T ) { std::cout << "T is pointer" << std::endl; }
っていうコードって,イチイチ enabler
を定義しなくても,
template < typename T, typename std::enable_if< std::is_arithmetic<T>::value >::type* = 0 > void f( T ) { std::cout << "T is arithmetic" << std::endl; } template < typename T, typename std::enable_if< std::is_pointer<T>::value >::type* = 0 > void f( T ) { std::cout << "T is pointer" << std::endl; }
でよくね? って思ったので,ちょっと試してみた.
が,うまくいかない. http://ideone.com/c9atG
結論から言うと,規格の 14.3.2/5 によれば,このコードは ill-formed で意図したようには動作せず,正しくは
template < typename T, typename std::enable_if< std::is_arithmetic<T>::value >::type* = nullptr > void f( T ) { std::cout << "T is arithmetic" << std::endl; } template < typename T, typename std::enable_if< std::is_pointer<T>::value >::type* = nullptr > void f( T ) { std::cout << "T is pointer" << std::endl; }
と書く必要があるみたいです. ( nullptr
は (void*)0
でも可.)
とはいえ,この動作は C++0x で追加された機能*1であり, GCC では未だ使えない*2為,
今でも問題なく使える enabler
を使うのが一番な気もします.
最新の GCC 4.7 で実装されました! これで enabler
なんて おさらばです.
…まぁ,正直, typename std::enable_if
なら,今でも使えるんですけどね.
*1:詳しくは本の虫の該当記事 http://cpplover.blogspot.com/2011/04/6c0x.html を参照のこと.