正しい転送を保証するために 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>
の目的ID テンプレートでは、テンプレート引数の推論が無効になります。このシナリオでこれが重要なのはなぜですか?
テンプレート引数の推論は、誤った型の推論につながります。型 X のオブジェクトへの右辺値参照がパラメーター型 T& のテンプレート関数に渡される場合、テンプレート引数の推定により T が X として推論され、パラメーター型 X& が生成されます。ただし、完全転送の場合、パラメーターには名前があるため、パラメーターは左辺値になります。したがって、 std::forward でテンプレート引数の推論を使用すると、推論されたパラメータの型が lvalue 参照または const lvalue 参照になります。
<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 のパラメーターがその名前により lvalue または const lvalue 参照として扱われるため、完全転送は失敗します。これにより、forward_with_deduction で不正な型推定が行われ、望ましくない static_cast セマンティクスが発生します。
std::forward の ID テンプレートでテンプレート引数の推定を無効にすると、std::forward が常に右辺値参照を返すようになります。これは、左辺値と右辺値の正しい完全転送。
以上がstd::forward がアイデンティティ テンプレートを使用してテンプレート引数の推論を無効にするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。