6

このコードはほとんどのコンパイラでコンパイルに失敗しますが、最初は 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 つの方法で問題を解決できます。

  1. "metafun" f() の定義を次のように変更します。

    template < typename T > typename T::type f(T) {}

  2. 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 除外ではなくエラーを引き起こすのはなぜですか?

4

2 に答える 2

4
于 2012-12-31T06:42:18.827 に答える
2

SFINAEはそこであなたを保護しません。型推定のにエラーが発生します。ただし、これは機能するはずです。

template < typename T, typename Type = typename T::type >
struct a_metafun { typedef Type type; };

デフォルトのテンプレート パラメータにアクセスT::typeすることで、置換時にこれが発生し、その時点でSFINAEが開始されます。

編集:もう少し考えた後、現在の実装が失敗する理由が正確にはわかりません。私は、コンパイルエラーを引き起こすメンバー typeをa_metafun 持っているためだと思います。メンバー型がまったくないtype場合は異なります。a_metafuntype

于 2012-12-31T06:14:09.280 に答える