2017-07-14 71 views
1

我是SFINAE的新手。我注意到:在C++中用SFINAE模板扣除

template <typename T> void f(T t) { t.Crash(); } // version 1 
void f(...) { } // The sink. 
f(1); 

template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2 
void f(...) { } // The sink. 
f(1); 
在第2版

,因爲SFINAE的,它不會引發任何錯誤,並選擇橢圓形水槽。但是爲什麼在版本1中,編譯器會停止並投訴?

SFINAE只適用於簽名而非身體嗎?所以在版本1中,它更喜歡模板函數,但是編譯器在什麼階段停止並拋出錯誤?

請您明確解釋關於模板重載解析的編譯器的處理階段

回答

4

但爲什麼在版本1,編譯器會停下來並抱怨?

template <typename T> void f(T t) { t.Crash(); } // version 1 
void f(...) { } // The sink. 
f(1); 

沒有取代在上述f模板化版本有故障,因爲T可以推斷爲int從呼叫f(1)。而按重載決策規則,該f<int>(int)超過f(...)


template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2 
void f(...) { } // The sink. 
f(1); 

有是有一個替代失效者優先,因爲,編譯器將需要推導Tint後推斷的it類型。它代替int代替int::iterator這是無效的。


SFINAE上的功能工作在創建有效函數模板專業化的情況下。

SFINAE只適用於簽名而非身體嗎?

你可以說類似的東西...在這些有效的代碼示例以一個戰利品:

//Just the declaration 
template <typename T> 
void f(T t); 

void f(...); 

int main(){ 
    f(1); //selects f<int>(int) 
} 

同時:

//just the declarations. 
template <typename T> 
void f(const T& t, typename T::iterator* it = nullptr); 

void f(...); 

int main(){ 
    f(1); //selects f(...) 
}