[英]C++ template overloading - wrong function called
template<typename T> T* Push(T* ptr);
template<typename T> T* Push(T& ref);
template<typename T, typename T1> T* Push(T1&& ref);
我有
int i = 0;
Push<int>(i);
但是編譯器稱它為模棱兩可。 big昧如何? 第二個功能顯然是首選匹配項,因為它更專業。 特別是因為T1 &&除非我明確轉發/移動它,否則不會綁定到左值。
對不起-我是一個int。 否則,這個問題將毫無意義,而且我想人們會推斷出它,因為它通常是循環迭代器。
如果i
是一個int,則第一個不可行。 最后兩個仍然存在。 然后,為了推導i
,第二個和第三個都產生相同的函數類型以進行重載解析( int&
作為參數)。 因此,您必須依靠部分排序。
但是,部分排序無法區分它們。 對於函數調用的部分排序上下文,僅使用參數來確定順序(並且不考慮示例中的返回類型),並且從它們中剝離任何引用修飾符。 因此,您將成功地在兩個方向上從一個參數推導出另一個的參數類型-兩種參數類型至少分別與其他參數一樣專門。 而且const都沒有應用,因此沒有一個比另一個更專業。
有一個問題報告占位符,旨在澄清與部分訂購期間右值/左值參考困難有關的所有內容。 有關詳細信息,請參見此Usenet問題 。
如果這兩個中的任何一個更專業,我會說它應該是第一個。 畢竟,它接受的論據要少於另一個論點(另一個論點是潛在的完美轉發者)。
特別是因為T1 &&除非我明確轉發/移動它,否則不會綁定到左值。
實際上,它將接受任何東西。 有類型的參數T&&
的模板將切換到“完美轉發-演繹模式”,將演繹出T
,如果它是一個右值參數的類型,並且左值參考改性劑添加的類型T
如果是左值。 因此,如果參數是左值,則生成的參數類型為T& &&
折疊為T&
,它接受左值的優良值(就像您的情況一樣)。
再看一遍,您似乎想做的就是重載通過移動對象來獲取對象的函數。 但是,由於對T&&
進行了特殊的扣除(見下文),因此無法使用。 只需擦除第一個函數,然后將代碼編寫為
template<typename T, typename T1> T* Push(T1&& ref) {
/* for lvalues, T1 is U& and rvalues it is U, with U being the
* argument type. */
T t1(std::forward<T1>(ref));
/* whatever needs to be done ... */
}
如果參數是右值,則將移動構造t1
如果參數是左值或T
沒有移動構造器,則復制ref
。 這僅是一個示例,根據實際用例,可能並不是您應該實際執行的操作。 我也不確定為什么這里有兩種模板參數類型。 我建議擺脫T
,而將typename remove_reference<T1>::type *
表示為返回類型。 這樣您就可以從論證推論中受益。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.