2015-04-07 42 views
13

我遇到了關於enable_if和模板特化的正確使用的問題。模板特化和enable_if問題

修改的例子(出於保密原因)後,這裏有一個可比的例子:

I have function called "less" that checks if 1st arg is less than 2nd arg. Let's say I want to have 2 different kinds of implementations depending on the type of input - 1 implementation for integer and another for double.

,我至今看起來像這樣的代碼 -

#include <type_traits> 
#include <iostream> 

template <class T, 
      class = typename std::enable_if<std::is_floating_point<T>::value>::type> 
    bool less(T a, T b) { 
    // .... 
} 

template <class T, 
      class = typename std::enable_if<std::is_integral<T>::value>::type> 
    bool less(T a, T b) { 
    // .... 
} 

int main() { 
    float a; 
    float b; 
    less(a,b); 
    return 0; 
} 

上面的代碼無法編譯因爲 - 它說我正在重新定義更少的方法。

錯誤是:

Z.cpp:15:19: error: template parameter redefines default argument 
      class = typename std::enable_if<std::is_integral<T>::value>::type> 

       ^
Z.cpp:9:19: note: previous default template argument defined here 
      class = typename std::enable_if<std::is_floating_point<T>::value>::type> 
       ^

Z.cpp:16:11: error: redefinition of 'less' 
    bool less(T a, T b) { 
     ^

Z.cpp:10:11: note: previous definition is here 
    bool less(T a, T b) { 
     ^

Z.cpp:23:5: error: no matching function for call to 'less' 
    less(a,b); 
    ^~~~ 

Z.cpp:15:43: note: candidate template ignored: disabled by 'enable_if' 
     [with T = float] 
      class = typename std::enable_if<std::is_integral<T>::value>::type> 
             ^
3 errors generated. 

有人能說出什麼是錯在這裏?

+0

基本上,由於您如何調用返回類型,您並未正確使用'enable_if'。 – Alex

+0

快速解決方案是將一個省略號參數'...'添加到其中一個模板,以便將它們視爲不同的重載。 – 0x499602D2

+1

或將簽名更改爲'template :: value> :: type * = nullptr>' – vsoftco

回答

18

默認模板參數不是函數模板簽名的一部分。所以在你的例子中,你有兩個相同的重載less,這是非法的。鐺抱怨默認參數的重新定義(這也是非法根據§14.1/ 12 [temp.param]),而GCC產生以下錯誤消息:

error: redefinition of ' template<class T, class> bool less(T, T) '

要修復錯誤移動enable_if表達從默認參數的虛擬模板參數

template <class T, 
      typename std::enable_if<std::is_floating_point<T>::value, int>::type* = nullptr> 
    bool less(T a, T b) { 
    // .... 
} 

template <class T, 
      typename std::enable_if<std::is_integral<T>::value, int>::type* = nullptr> 
    bool less(T a, T b) { 
    // .... 
} 

另一種選擇是在返回類型使用enable_if,但我覺得這是難以閱讀。

template <class T> 
     typename std::enable_if<std::is_floating_point<T>::value, bool>::type 
     less(T a, T b) { 
    // .... 
} 

template <class T> 
    typename std::enable_if<std::is_integral<T>::value, bool>::type 
    less(T a, T b) { 
    // .... 
} 
+0

從技術上講,第一組代碼是不合格的根據標準,因爲'void *'不是模板非類型參數的有效類型。在實踐中,沒有我知道的編譯器實際上關心。雖然這個問題的解決辦法很簡單。 –

+0

@ T.C。 TIL ...感謝您指出這一點 – Praetorian

+0

我改變了它是一個函數參數,現在工作 – user855