592 votes

Quels sont les principaux objectifs de l'utilisation de std::forward et les problèmes qu'il résout ?

Dans un acheminement parfait, std::forward est utilisé pour convertir les références rvalue nommées t1 y t2 à des références rvalue non nommées. Quel est l'intérêt de faire cela ? Comment cela affecterait-il la fonction appelée inner si nous partons t1 & t2 en tant que valeurs l ?

template <typename T1, typename T2>
void outer(T1&& t1, T2&& t2) 
{
    inner(std::forward<T1>(t1), std::forward<T2>(t2));
}

5voto

colin Points 61

Il peut être utile de souligner que forward doit être utilisé en tandem avec une méthode externe avec forwarding/référence universelle. L'utilisation de forward par lui-même comme les déclarations suivantes est autorisée, mais ne sert à rien si ce n'est à créer la confusion. Le comité de normalisation pourrait vouloir désactiver cette flexibilité, sinon pourquoi ne pas utiliser static_cast à la place ?

     std::forward<int>(1);
     std::forward<std::string>("Hello");

À mon avis, move et forward sont des patrons de conception qui sont des résultats naturels après l'introduction du type de référence r-value. Nous ne devrions pas nommer une méthode en supposant qu'elle est correctement utilisée, sauf si une utilisation incorrecte est interdite.

0 votes

Je ne pense pas que le comité C++ estime qu'il lui incombe d'utiliser "correctement" les idiomes du langage, ni même de définir ce qu'est une utilisation "correcte" (bien qu'il puisse certainement donner des lignes directrices). À cette fin, alors que les enseignants, les patrons et les amis d'une personne peuvent avoir le devoir de l'orienter dans une direction ou une autre, je pense que le comité C++ (et donc la norme) n'a pas ce devoir.

0 votes

Oui, je viens de lire N2951 et je conviens que le comité de normalisation n'a pas l'obligation d'ajouter des limitations inutiles concernant l'utilisation d'une fonction. Mais les noms de ces deux modèles de fonction (move et forward) sont en effet un peu déroutants si l'on ne voit que leurs définitions dans le fichier de bibliothèque ou dans la documentation standard (23.2.5 Forward/move helpers). Les exemples dans la norme aident certainement à comprendre le concept, mais il pourrait être utile d'ajouter plus de remarques pour rendre les choses un peu plus claires.

1voto

Sorush Points 92

D'un autre point de vue, lorsqu'il s'agit de rvalues dans une affectation de référence universelle, il peut être souhaitable de préserver le type d'une variable tel qu'il est. Par exemple

auto&& x = 2; // x is int&&

auto&& y = x; // But y is int&    

auto&& z = std::forward<decltype(x)>(x); // z is int&&

Utilisation de std::forward nous avons veillé à z a exactement le même type que x .

De plus, std::forward n'affecte pas les références lvalue :

int i;

auto&& x = i; // x is int&

auto&& y = x; // y is int&

auto&& z = std::forward<decltype(x)>(x); // z is int&

Toujours z a le même type que x .

Donc, pour en revenir à votre cas, si la fonction interne a deux surcharges pour les éléments suivants int& y int&& vous voulez passer des variables comme z affectation non y un.

Les types de l'exemple peuvent être évalués via :

std::cout<<is_same_v<int&,decltype(z)>;
std::cout<<is_same_v<int&&,decltype(z)>;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X