2012-12-20 10 views
23

なぜgcc48とclang32でコンパイルされないのですか?enable_ifでコンパイルエラーが発生する理由

#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; 
      ^

EDIT - SOLUTION

私は実用的な理由のために、チャールズサルビアからの答えを受け入れてきたI提案された回避策を使用できませんでした(Nに特化しています)。私は私のために働く他の回避策を見つけました。

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

を印刷しますが、あなたはこれがとにかく仕事に行くされてよろしいですか? 'enable_if'が単純なテンプレートクラスであると仮定しているのではなく、言語構造体として実装されていない限り、戻り値の型だけでメソッドをオーバーロードすることはできません。 – zneak

+0

enable_ifをTに依存する必要があるのはなぜですか? –

+0

解決策は私のためには機能しません!私は 'エラー:呼び出しのための一致する機能がありませんでした... ' –

答えて

14

あなたが関数テンプレートでテンプレートパラメータTを使用せずにenable_ifを使用するので:enable_ifTに依存してください。構造体Sに特定のテンプレートパラメータ値Nがあるときに特化したい場合は、クラステンプレートの特殊化を使用する必要があります。

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

template <int N> 
struct S<N, typename std::enable_if<N == 1>::type> 
{ 
    .... 
}; 
5

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); } 
}; 
+1

[この質問](http:// stackoverflow。com/questions/6972368/stdenable-if-to-conditionally-compile-a-member-function)にはいくつかの情報があります。 – Anthony

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); 
} 
6

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

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;}; 
}; 
7

まあ、私はあなたがやりたいのかわからないけど、多分このコードは役立ちます:

#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

関連する問題