簡體   English   中英

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

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM