2012-12-20 62 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; 
      ^

編輯 - 解決方案:

我接受的答案,從查爾斯丹蔘,但實際原因我無法使用建議的解決方法(專門針對N)。我找到了適用於我的其他解決方法。讓enable_if取決於T

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

你確定這是去反正工作?你不能僅僅通過它們的返回類型來重載方法(除非'enable_if'被實現爲一種語言結構,而不是像我現在所假設的那樣實現一個簡單的模板化類)。 – zneak

+0

爲什麼使enable_if的解決方法完全依賴於T所必需的? –

+0

該解決方案對我無效!我得到了'錯誤:沒有匹配的調用函數...' –

回答

14

由於您使用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> 
{ 
    .... 
}; 
5

要獲得std::enable_if喜歡這個工作,你是靠SFINAE。不幸的是,點在哪裏聲明

S<1> s1; 

它將實例所有S<1>的成員聲明。如果S<1>是一個不合格的構造,SFINAE只會在這一點上發揮作用。不是這樣。不幸的是,它包含一個無效的函數,因此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