sfinaeのenabler 2/2
じゃあenablerについてのど素人丸出し糞的外れな疑問をかくよー。
/////////////////////////////////コード始まり
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;
}
////////////////////////////コード終わり
sfinaeについての例を探すとこんなのが出てくる(このコードは巷で有名な江添さんのサイト
本の虫: C++0xにおけるenable_ifの新しい使い方
から持ってきました)
「なんでenablerで初期化してリンカエラーにならないの?」
だって,たとえTがarithmeticで、eneble_if::typeがvoidだとして、void*& を enablerデフォルト実引数初期化するときに,enablerの定義がいるはずじゃん(それがそもそも違うのかもしれんけど)
というわけでこんな風に変更してみた
std::enable_if<std::is_arithmetic<T>::value >::type * = static_cast<void*>(&enabler )>
参照を外してenablerのアドレスを渡すようにしました
vc++では通った。ideoneでは駄目だった。こんなこと言われた
prog.cpp:13:87: error: could not convert template argument ‘(void*)(& enabler)’ to ‘std::enable_if<true, void>::type* {aka void*}’
わけわかんない
つぎに、enable_ifの部分は最初に書いたとおりに戻して、main関数にこれ入れてみた
f<int, enabler>(arithmetic);
vc++もideoneも通った。(しかしvc++のいんてりせんすは 1 IntelliSense: オーバーロードされた関数 "f" のインスタンスが引数リストと一致しません
引数の型: (int) とか言ってくる。コンパイル通って実行できるけど)
ちょっと外れて、main関数にこういうのを入れてみる
void* foo = &enabler
vc++通らない。未解決だそうだ。ideone通る。へー。
とまぁこんな風に、externがらみの奴がすっごいわかんない。
規格をよんでも、リンカについての詳しい話が見つかんないし、externalな変数が参照できる条件も見つからん。俺が見落としてるのか、実装依存なのか。
そうはいっても、テンプレートのデフォルト実引数にenablerを使うってのはboostライブラリに採用されているらしい。つまり合法であるという根拠があるはずなの。
あー見つかんないわかんない。