31

なぜこれはgcc48とclang32でコンパイルされないのですか?

#include <type_traits>

template <int N> 
struct S {

    template<class T> 
    typename std::enable_if<N==1, int>::type
    f(T t) {return 1;};

    template<class T> 
    typename std::enable_if<N!=1, int>::type
    f(T t) {return 2;};
};

int main() {
    S<1> s1;
    return s1.f(99);
}

GCCエラー:

/home/lvv/p/sto/test/t.cc:12:2: error: no type named ‘type’ in ‘struct enable_if<false, int>’
  f(T t) {return 2;};
  ^

CLANGエラー:

/home/lvv/p/sto/test/t.cc:11:26: error: no type named 'type' in 'std::enable_if<false, int>'; 'enable_if' cannot be used to
      disable this declaration
        typename std::enable_if<N!=1, int>::type
                                ^~~~
/home/lvv/p/sto/test/t.cc:16:7: note: in instantiation of template class 'S<1>' requested here
        S<1> s1;
             ^

編集-ソリューション

Charles Salviaからの回答を受け入れましたが、実際的な理由から、提案された回避策(Nに特化)を使用できませんでした。私は私のために働く他の回避策を見つけました。依存enable_ifさせるT

typename std::enable_if<(sizeof(T),N==1), int>::type
4

5 に答える 5

21

関数テンプレートでenable_ifテンプレート パラメーターを使用せずに使用するためです。T構造体Sに特定のテンプレート パラメーター値がある場合に特化する場合は、Nクラス テンプレートの特化を使用する必要があります。

template <int N, class Enable = void> 
struct S {  };

template <int N>
struct S<N, typename std::enable_if<N == 1>::type>
{
  ....
};
于 2012-12-20T02:41:14.383 に答える
10

何をしたかったのかよくわかりませんが、次のコードが役立つかもしれません。

#include <iostream>

template <int N>
struct S {

    template<class T=int>
    typename std::enable_if<N==1, T>::type
    f(T t) {return 1;}

    template<class T=int>
    typename std::enable_if<N!=1, T>::type
    f(T t) {return 2;}
};

int main()
{
    S<1> s1;
    S<2> s2;
    std::cout << s1.f(99) << " " << std::endl << s2.f(5);
}

これにより、1 と 2 が出力されます。

于 2014-10-31T15:28:29.497 に答える
9

このstd::enable_ifような作業を行うには、SFINAE に依存しています。残念ながら、あなたが宣言する時点で

S<1> s1;

S<1>のすべてのメンバー宣言をインスタンス化します。SFINAE は、この時点でS<1>不適切な構成である場合にのみ機能します。そうではない。残念ながら、無効な関数が含まれているため、 のインスタンス化S<>は無効です。

このようなことについては、別のテンプレート構造体に委ねるかもしれません:

template <bool B>
struct f_functor {
    template <typename T>
    static int f(T t) { return 1; }
};

template <>
struct f_functor<false> {
    template <typename T>
    static int f(T t) { return 2; }
};

template <int N> 
struct S {

    template<class T> 
    typename int f(T t) { return f_functor<N==1>::f(t); }
};
于 2012-12-20T02:51:14.573 に答える
8

次のように、デフォルトのブール値テンプレート パラメータを使用します。

template <int N> 
struct S {

    template<class T, bool EnableBool=true> 
    typename std::enable_if<N==1 && EnableBool, int>::type
    f(T t) {return 1;};

    template<class T, bool EnableBool=true> 
    typename std::enable_if<N!=1 && EnableBool, int>::type
    f(T t) {return 2;};
};
于 2014-08-16T20:46:52.617 に答える
1

この場合、enable_if をまったく使用しないことを考えることができます。f を単純に特殊化することができます。

template <int N> 
struct S {
    template<class T> int f(T t);
};

template<int N>
template<class T>
int S<N>::f(T t) { return 2; }

template<>
template<class T>
int S<1>::f(T t) { return 1; }

int main() {
    S<1> s1;
    return s1.f(99);
}
于 2012-12-20T08:50:16.473 に答える