2010-06-06 33 views
2
 template<typename T> T* Push(T* ptr); 
     template<typename T> T* Push(T& ref); 
     template<typename T, typename T1> T* Push(T1&& ref); 

C++模板重載 - 錯誤的函數調用

 int i = 0; 
     Push<int>(i); 

但是編譯器調用它明確。這是怎麼模糊的?第二個功能顯然是首選,因爲它更專業化。特別是因爲T1 & &將不會綁定到一個左值,除非我明確地轉發/移動它。

對不起 - 我是一個int。否則,這個問題將毫無意義,我認爲人們會推斷它,因爲它通常是循環迭代器。

+0

我不知道'我'是什麼? – 2010-06-06 15:24:51

+0

「我」是什麼類型?你正在使用哪種編譯器?如果錯誤的函數被調用,如果編譯器說它是不明確的(那麼它應該只是產生一個錯誤)? – jalf 2010-06-06 15:28:21

回答

7

如果i是一個int,那麼第一個是不可行的。最後兩個保持。然後,爲了扣除i,第二個和第三個產生用於重載分辨率的相同功能類型(作爲參數int&)。所以你必須依靠部分排序。

但是,部分排序無法區分它們。對於函數調用部分排序上下文,只有參數用於確定一個順序(並且不考慮示例中的返回類型),並且任何引用修飾符都從它們中剝離。因此,您將成功推導出兩個方向上的參數類型 - 兩種參數類型都至少與其他參數相同。而且const也沒有應用,所以都不是比其他更專業。

有一個問題報告佔位符,旨在澄清與部分排序中的右值/左值引用困難相關的任何事情。詳細信息請參見this usenet question

如果兩者中的任何一個應該更專業化,我會說它應該是第一個。畢竟,它比另一個接受更少的論據(另一個是潛在的完美的貨運代理)。


特別是由於T1 & &不會綁定到左值,除非我明確前進/移動。

其實,它會接受任何東西。在模板中有一個T&&類型的參數將切換到「perfect-forwarding-deduction-mode」,它將推斷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如果參數是一個右值,並複製ref如果參數是一個左值或者T不具有移動構造函數。這只是一個例子,根據你的實際用例,它可能不是你應該做的。我也不確定你爲什麼在這裏有兩個模板參數類型。我建議擺脫T,並說typename remove_reference<T1>::type *爲返回類型,而不是。這樣你可以從爭論中扣除。