2014-10-29 13 views
2

我試圖在函數參數上使用std::enable_if來觸發SFINAE。編譯失敗,此錯誤:扣除參數失敗,返回值工作

type_nonsense.cpp:20:5: error: no matching function for call to 'c' 
    c(SOME::VALUE); 
    ^
type_nonsense.cpp:13:6: note: candidate template ignored: couldn't infer 
     template argument 'T' 
void c(typename std::enable_if<std::is_enum<T>::value, T>::type t) {} 
    ^
1 error generated. 

移動std::enable_if要麼返回類型或虛擬模板參數正常工作。爲什麼?


#include <type_traits> 

// Works 
template <typename T, typename dummy = typename std::enable_if<std::is_enum<T>::value, T>::type> 
void a(T t) {} 

// Works 
template <typename T> 
typename std::enable_if<std::is_enum<T>::value, void>::type b(T t) {} 

// Fails to compile 
template <typename T> 
void c(typename std::enable_if<std::is_enum<T>::value, T>::type t) {} 

enum class SOME { VALUE }; 

int main() { 
    a(SOME::VALUE); 
    b(SOME::VALUE); 
    c(SOME::VALUE); 
} 
+0

' template void func(std :: vector :: iterator)'出於完全相同的原因失敗,與SFINAE無關。 – 2014-10-29 19:34:17

回答

5

嵌套名稱說明符中的依賴類型是用於模板參數推導的非推導上下文,因此不能用於確定T的類型。將std::enable_if放在返回類型中或作爲默認模板參數可以工作,因爲在這些上下文中不會推導出T的類型。

如果你需要把它作爲一個參數,你可以這樣做是這樣的:

template <typename T> 
void c(T t, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr) {} 

這工作,因爲T正由第一的說法,而不是第二推斷。

+0

只是好奇,但會有什麼情況下你不能把它放在回報? – 2014-10-29 19:54:51

+0

@JamesKanze 14.8.2/7([temp.deduct]/p7)給出了一個很好的例子,如果在參數列表之前的返回類型中使用了依賴嵌套名稱說明符的結果將導致失敗或成功,類型或參數列表中。 – 0x499602D2 2014-10-29 20:06:14

1

對於從而未能編譯一個,T不扣除。