2017-09-13 30 views
2

考慮下面的例子(godbolt):編譯它提供了以下錯誤調用帶有自變量的函數隱式轉換爲模板類的一個對象

template <typename T> 
struct S { 
    S(int) {} 
}; 

template <typename T> 
void f(S<T>, T) {} 

int main() { 
    f(1, 2); 
} 

<source>: In function 'int main()': 
10 : <source>:10:11: error: no matching function for call to 'f(int, int)' 
    f(1, 2); 
     ^
7 : <source>:7:6: note: candidate: template<class T> void f(S<T>, T) 
void f(S<T>, T) {} 
    ^
7 : <source>:7:6: note: template argument deduction/substitution failed: 
10 : <source>:10:11: note: mismatched types 'S<T>' and 'int' 
    f(1, 2); 
     ^

製作S非-template使示例編譯。

儘管隱式從int轉換爲S<T>,但爲何不編譯此代碼?

+0

'T'不能在'S '中推導出來。這可能看起來很奇怪,但考慮只有從「int」到「S 」的轉換存在的情況,「T」應該是什麼? –

+0

或者'S '沒有那個構造函數 –

+0

請注意'f (1,2)'[compiles fine](https://ideone.com/DoOa3F)。 – dasblinkenlight

回答

3

模板函數不是函數。它們是寫函數的模板。

template <typename T> 
void f(S<T>, T) {} 

這是一個用於編寫給定類型爲T的函數的模板。

現在,C++在某些情況下會嘗試爲您推導出T。它在模式匹配每個參數(一次)。

如果任何參數未能找到匹配,或者推導出的類型不一致或不完整,則扣除失敗。未嘗試轉換或部分匹配。如果找到匹配,則將其添加爲考慮過載的候選項(此處有一些規則),然後超載分辨率開始執行。

在重載分辨率時考慮時間轉換。在模板類型扣除它不是轉換爲基地以外。

在你的情況下,S<T>不能從1推斷出T的類型。所以扣除只是失敗。在考慮轉換的情況下,我們從未達到超負荷分辨率

碰巧你可以從扣除期間考慮的塊參數:

template<class T>struct tag_t{using type=T;}: 
template<class T>using block_deduction=typename tag_t<T>::type; 

template <typename T> 
void f(block_deduction<S<T>>, T) {} 

,現在你的主編譯。

相關問題