このコードはほとんどのコンパイラでコンパイルに失敗しますが、最初は SFINAE が私を保護してくれると直感的に期待していました。
typedef void (*A)();
template < typename T >
struct a_metafun { typedef typename T::type type; };
template < typename T >
typename a_metafun<T>::type f(T) {}
template < typename T>
void f(T(*)()) {}
int main() { f(A()); }
少なくとも 2 つの方法で問題を解決できます。
"metafun" f() の定義を次のように変更します。
template < typename T > typename T::type f(T) {}
a_metafun
分析T
して型がある場合は型を持ち、型T
がない場合は型を持たないように定義します...しかし、どちらの方法でもエラーなしでインスタンス化します。BOOST_MPL_HAS_XXX_TRAIT_DEF(type) typedef < template T, bool = has_type<T>::value > struct a_metafun { }; typedef < template T > struct a_metafun<T, true> { typedef typename T::type type };
14.8.2 (C++03) を見ると、SFINAE が適用できる条件を正確に指定しているように見えます。どこか見やすい場所はありますか?すでに推定されたテンプレートのインスタンス化での失敗は、別の推定中であっても、このリストには含まれていないようです。
これを違法にする理由を解釈するために私が取った別の方向は、 a_metafun の推定が既に行われており、その内部のインスタンス化がエラーの原因であるということです。SFINAE はインスタンス化中に適用されず、控除中にのみ適用されますか、それとも間違っていますか? ただし、2 番目のケースでは、a_metafun は正しく、適切な形式でインスタンス化されていますが、単に「型」定義が含まれていません。つまり、インスタンス化しようとしているテンプレートが置換のために失敗しています。
基本的に、標準で私が目撃している動作を指定しているものは何なのか疑問に思っています。私が試したすべてのコンパイラは文句を言います。私は彼らがそうすることで正しいと考えていますが、その理由については完全にはわかりません.
では、専門家の皆さん...何が何ですか? f() の演繹のコンテキストであっても、型のインスタンス化が SFINAE 除外ではなくエラーを引き起こすのはなぜですか?