停用std::forward 的範本參數推導以確保正確轉送
考慮VS2010 中std::forward 的定義:
<code class="cpp">template<class _Ty> inline _Ty&& forward(typename identity<_Ty>::type& _Arg) { // forward _Arg, given explicitly specified type parameter return ((_Ty&&)_Arg); }</code>身分範本的目的是停用範本參數推導。為什麼這在這種情況下至關重要? 模板參數推導會導致錯誤的類型推導。如果類型 X 的物件的右值參考傳遞給參數類型為 T& 的模板函數,則模板實參推導會將 T 推斷為 X,從而產生參數類型 X&。然而,對於完美轉發,參數是左值,因為它有名稱。因此,在 std::forward 中使用模板參數推導將導致推導的參數類型成為左值參考或 const 左值參考。
<code class="cpp">template<typename T> T&& forward_with_deduction(T&& obj) { return static_cast<T&&>(obj); }</code>考慮以下範例:
<code class="cpp">void test(int&){} void test(const int&){} void test(int&&){} template<typename T> void perfect_forwarder(T&& obj) { test(forward_with_deduction(obj)); } int main() { int x; const int& y(x); int&& z = std::move(x); test(forward_with_deduction(7)); // 7 is an int&&, correctly calls test(int&&) test(forward_with_deduction(z)); // z is treated as an int&, calls test(int&) // All the below call test(int&) or test(const int&) because in perfect_forwarder 'obj' is treated as // an int& or const int& (because it is named) so T in forward_with_deduction is deduced as int& // or const int&. The T&& in static_cast<T&&>(obj) then collapses to int& or const int& - which is not what // we want in the bottom two cases. perfect_forwarder(x); perfect_forwarder(y); perfect_forwarder(std::move(x)); perfect_forwarder(std::move(y)); }</code>在此範例中,完美轉送失敗,因為Perfect_forwarder 中的參數因其名稱而被視為左值或const 左值引用。這會導致forward_with_deduction中的類型推導不正確,產生不必要的static_cast語意。 在std::forward中停用具有身分範本的範本參數推導可確保std::forward始終傳回右值引用,這對於正確完美轉送左值和右值。
以上是為什麼 std::forward 使用恆等模板來停用模板參數推導?的詳細內容。更多資訊請關注PHP中文網其他相關文章!