"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > 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 ?

Publié le 2024-11-09
Parcourir:750

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 :

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

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.

template
T&& forward_with_deduction(T&& obj)
{
    return static_cast

Considérez l'exemple suivant :

void test(int&){}
void test(const int&){}
void test(int&&){}

template
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));
}

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 des arguments 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 valeurs l ainsi que des valeurs r.

Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3