2017-06-18 74 views
13

考慮下面的代碼:爲什麼編譯器在與轉換運算符一起使用時不能推導出模板參數?

#include <utility> 

template<typename T> 
struct wrapper { 
    T value; 
}; 

struct foo { 
    operator wrapper<int>() { 
     return{10}; 
    } 
}; 


int main() { 
    foo f; 
    wrapper w = f; // error 
    std::pair p = std::make_pair(1, 0); // ok 
} 

gcc 7.1.1未能在標線來編譯上面:

main.cpp: In function 'int main()': 
main.cpp:17:17: error: class template argument deduction failed: 
    wrapper w = f; // error 
       ^
main.cpp:17:17: error: no matching function for call to 'wrapper(foo&)' 
main.cpp:4:8: note: candidate: template<class T> wrapper(wrapper<T>)-> wrapper<T> 
struct wrapper { 
     ^~~~~~~ 
main.cpp:4:8: note: template argument deduction/substitution failed: 
main.cpp:17:17: note: 'foo' is not derived from 'wrapper<T>' 
    wrapper w = f; // error 
       ^

f可轉換爲wrapper<int>,所以我希望這樣的事情發生。從那裏編譯器應該能夠推斷出Tint。但它不能。

編譯器可以正確推導出std::pair的模板參數,所以我想知道爲什麼這不是wrapper

任何想法?

+0

IMO如果類模板扣除查看轉換運算符,會引起混淆。如果需要的話,應該使用明確的扣除指南。 – cpplearner

+0

相關:https://stackoverflow.com/q/43019240/1896169 – Justin

+0

這是什麼'運算符結構包裝()'?它是否聲明'operator wrapper'或'operator()'? – cat

回答

11

對於類模板參數推導,「過載集」的組成如[over.match.class.deduct/1]中所述。那些有以下幾種:

形成一組的功能和功能模板,包括:
(1.1) - 對指定 由模板名稱,如果模板被定義的主類模板的每個構造,函數模板 具有以下屬性:
(1.1.1) - 模板參數是 類模板的模板參數隨後模板 參數(包括默認模板參數)的構造的, 如果有的話。
(1.1.2) - 函數參數的類型是構造函數的 。
(1.1.3) - 返回類型是模板名稱指定的類模板 ,模板參數 對應於從類 類獲得的模板參數。 (1.2) - 如果未定義主類模板C或不聲明任何構造函數,則從假設的構造函數C()中派生出如上所示的 的附加函數模板。

(1.3) - 從 假設構造函數C(C)導出的額外函數模板,稱爲複製推理候選。

(1.4) - 對每個扣導,具有 函數或函數模板以下屬性:
(1.4.1) - 模板參數(如果有) 和功能參數是那些deduction-的指南。
(1.4.2) - 返回類型是扣減指南的簡單模板標識。

正如你所看到的,在1.1匹配「功能」只嘗試參數類型匹配的模板參數類型正是。它不考慮轉換(與大多數其他模板演繹相關的行爲非常相似)。

它適用於std::pair的原因歸因於項目1.3和它定義的「複製扣除候選項」。

相關問題