C++ 初心者です。
先日、 SFINAE という仕様があると言うことを耳にしました。
面白がっていろいろと試していたのですが、途中で疑問に当たりました。
まず SFINAE について確認させてください。
私は、「テンプレートを型に置き換えるときに文法上のエラーがあった場合は、それをオーバーロード候補から外し(エラーとせず)続行」だと認識しています。
ここで型に置き換えるときのエラーとは、単純には例えば std::enable_if<false>::type
などと言う型はない、のようなものだと思っています。
もし誤解があれば、お教えください。
ここで次のようなコードについて考えます。
Code 1:
C++
1extern void* enabler; 2template <typename T, typename std::enable_if<std::is_same<T, int>::value>::type*& = enabler> 3void foo(T) {} 4template <typename T, typename std::enable_if<std::is_same<T, long>::value>::type*& = enabler> 5void foo(T) {}
いわゆる enabler を使うコードです。
上のコードは T が int か long かによって正しく呼び分けられますよね。これは理解できました。
ところが
Code 2:
C++
1template <typename T, typename = typename std::enable_if<std::is_same<T, int>::value>::type> 2void foo(T) {} 3template <typename T, typename = typename std::enable_if<std::is_same<T, long>::value>::type> 4void foo(T) {}
このようにするとコンパイラに怒られます。
しかしこのコードは T が int のとき、std::enable_if<std::is_same<int, long>::value>::type が存在しないので、下側の関数がオーバーロード候補から外されるのではと思うのですが、どういうことなのでしょうか。
コンパイラのエラーは
error: template parameter redefines default argument template <typename T, typename = typename std::enable_if<std::is_same<T, long>::value>::type>
です(Clang 3.7.1)。
読む限りではきっとシグネチャ?が同じなのでオーバーロードできないということなのでしょうが、そうだと言うのなら enabler を用いた例が通るのが逆に不思議に思えてしまいます。
長くなりましたが、要するにお聞きしたいことは Code 1 が 許されて、 Code 2 が許されない理由です。
###補足情報(言語/FW/ツール等のバージョンなど)
Clang (3.7.1), C++14
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/04/12 14:37
2016/04/12 15:05
2016/04/12 15:38
2016/04/12 15:49
2016/04/12 15:55
2016/04/12 16:03
2016/04/12 17:46
2016/04/13 10:35
2016/04/13 10:37
2016/04/13 15:22
2016/04/13 15:39 編集
2016/04/13 16:16
2016/04/13 17:09 編集
2016/04/14 12:53
2016/07/29 18:31