ホームページ >バックエンド開発 >C++ >std::forward がアイデンティティ テンプレートを使用してテンプレート引数の推論を無効にするのはなぜですか?

std::forward がアイデンティティ テンプレートを使用してテンプレート引数の推論を無効にするのはなぜですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-11-09 09:34:02682ブラウズ

Why does std::forward use the identity template to disable template argument deduction?

正しい転送を保証するために std::forward によるテンプレート引数の推論を無効にする

VS2010 の std::forward の定義を検討してください:

<code class="cpp">template<class _Ty> inline
_Ty&amp;&amp; forward(typename identity<_Ty>::type&amp; _Arg)
{   // forward _Arg, given explicitly specified type parameter
    return ((_Ty&amp;&amp;)_Arg);
}</code>

の目的ID テンプレートでは、テンプレート引数の推論が無効になります。このシナリオでこれが重要なのはなぜですか?

テンプレート引数の推論は、誤った型の推論につながります。型 X のオブジェクトへの右辺値参照がパラメーター型 T& のテンプレート関数に渡される場合、テンプレート引数の推定により T が X として推論され、パラメーター型 X& が生成されます。ただし、完全転送の場合、パラメーターには名前があるため、パラメーターは左辺値になります。したがって、 std::forward でテンプレート引数の推論を使用すると、推論されたパラメータの型が lvalue 参照または const lvalue 参照になります。

<code class="cpp">template<typename T>
T&amp;&amp; forward_with_deduction(T&amp;&amp; obj)
{
    return static_cast<T&amp;&amp;>(obj);
}</code>

次の例を考えてみましょう:

<code class="cpp">void test(int&amp;){}
void test(const int&amp;){}
void test(int&amp;&amp;){}

template<typename T>
void perfect_forwarder(T&amp;&amp; obj)
{
    test(forward_with_deduction(obj));
}

int main()
{
    int x;
    const int&amp; y(x);
    int&amp;&amp; z = std::move(x);

    test(forward_with_deduction(7));    //  7 is an int&amp;&amp;, correctly calls test(int&amp;&amp;)
    test(forward_with_deduction(z));    //  z is treated as an int&amp;, calls test(int&amp;)

    //  All the below call test(int&amp;) or test(const int&amp;) because in perfect_forwarder 'obj' is treated as
    //  an int&amp; or const int&amp; (because it is named) so T in forward_with_deduction is deduced as int&amp; 
    //  or const int&amp;. The T&amp;&amp; in static_cast<T&amp;&amp;>(obj) then collapses to int&amp; or const int&amp; - 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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。