Maison >développement back-end >C++ >Pourquoi std::forward utilise-t-il le modèle d'identité pour désactiver la déduction des arguments du modèle ?

Pourquoi std::forward utilise-t-il le modèle d'identité pour désactiver la déduction des arguments du modèle ?

Susan Sarandon
Susan Sarandonoriginal
2024-11-09 09:34:02683parcourir

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

Désactivation de la déduction d'argument de modèle avec std::forward pour garantir un transfert correct

Considérez la définition de std::forward dans VS2010 :

<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>

Le but du modèle d'identité est de désactiver la déduction des arguments du modèle. Pourquoi est-ce crucial dans ce scénario ?

La déduction d’argument de modèle conduirait à une déduction de type incorrecte. Si une référence rvalue à un objet de type X est transmise à une fonction modèle avec un type de paramètre T&, la déduction de l'argument du modèle déduirait T comme X, ce qui donnerait un type de paramètre X&. Cependant, pour un transfert parfait, le paramètre est une lvalue car il a un nom. Par conséquent, l'utilisation de la déduction d'argument de modèle dans std::forward ferait en sorte que le type de paramètre déduit soit une référence lvalue ou une référence 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>

Considérez l'exemple suivant :

<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>

Dans cet exemple, le transfert parfait échoue car le paramètre dans perfect_forwarder est traité comme une référence lvalue ou const lvalue en raison de son nom. Cela conduit à une déduction de type incorrecte dans forward_with_deduction, entraînant une sémantique static_cast indésirable.

La désactivation de la déduction d'argument de modèle avec le modèle d'identité dans std::forward garantit que std::forward renvoie toujours une référence rvalue, ce qui est essentiel pour transmission parfaite et correcte des lvalues ​​ainsi que des rvalues.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn