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
Libérer: 2024-11-09 09:34:02
original
718 Les gens l'ont consulté

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>
Copier après la connexion

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>
Copier après la connexion

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>
Copier après la connexion

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 de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal