Reliure structurée pour remplacer std :: tie abuse

En lisant ce résumé des dernières fonctionnalités du c ++ 17, j’ai été un peu surpris par la section sur les liaisons structurées (c’est moi qui souligne):

liaisons structurées

Jusqu’à présent, il était connu d’utiliser un truc pour abuser de std :: tie afin d’affecter directement un tuple ou une paire à différentes variables, au lieu de devoir traiter le type de résultat manuellement. C’était un hack , et les variables devaient exister, maintenant vous pouvez les déclarer et les initialiser sur une seule ligne:

auto [a, b, c] = getvalues ​​();

Les accolades sont nécessaires, getvalues ​​renvoie un tuple. std :: pair n’est pas mentionné dans la proposition. Par conséquent, il est difficile de savoir si cela fonctionne avec pair, qui est renvoyé par la STL dans certaines méthodes d’insertion.

Je suppose qu’ils font référence à ce type d’utilisation de std::tie

 int a,b,c; std::tie(a,b,c) = std::make_tuple(1,2,3); 

que je croyais être une pratique recommandée.

Quelqu’un peut-il offrir une explication de la raison pour laquelle ils se réfèrent à l’exemple ci-dessus comme un piratage?

Je peux le dire simplement comme ça:

Dans un langage où les fonctions peuvent renvoyer une seule variable

 int a,b,c; std::tie(a,b,c) = function_returning_multiple_values(); 

est un hack pour:

 auto [a, b, c] = function_returning_multiple_values(); 

tout comme dans le monde hypothétique où C ++ autoriserait un seul paramètre pour les fonctions

 int p1, p2, p3; p1 = ...; p2 = ...; p3 = ...; function_taking_multiple_params(std::tie_params(p1, p2, p3)); 

serait un hack pour:

 function_taking_multiple_params(p1, p2, p3) 

Vous êtes tellement habitué à la ressortingction C ++ qu’une fonction peut renvoyer au plus un object, mais c’est en fait une ressortingction de langue artificielle, tout comme une ressortingction à accepter au plus un paramètre serait une ressortingction de langue artificielle.

std::tie est un hack de bibliothèque pour une fonctionnalité de langue manquante. Et cela présente des inconvénients:

  • les variables doivent être déclarées à l’avance
  • les types de variables doivent être déclarés explicitement
  • Inefficace ou ne peut pas être utilisé avec des types qui ne sont pas constructibles par défaut

Les liaisons structurées sont-elles tout ce qu’elles auraient pu être? Non, mais dans la plupart des cas, ils représentent tout ce dont nous avons besoin.

Que manque-t-il?

  • Type explicite pour certains éléments: par exemple:
 auto [a, std::ssortingng b, c] = foo(); 

a et c ont le type déduit et b est explicite “std :: ssortingng”

  • Nesting. Par exemple:
 auto [a, [b1, b2], c] = foo(); 

où le deuxième object renvoyé de foo est un object semblable à un tuple .

  • Fonction de langue sur le site de retour (en contournant std::tuple tous ensemble):
 auto foo() -> [int, int] 

au lieu de

 auto foo() -> std::tuple 
  • Objets de retour nommés
 auto foo() -> [int& key, int& value] 

… bien … ça ne serait pas gentil

  • et combinez cela avec … – préparez-vous pour un nouveau nom sympa – Initialisation du retour généralisé:
 auto minmax_element(It begin, It end) -> [It min_it, It max_it]; auto [min = *min_it, max = *max_it] = minmax_element(...); 

std::tie en soi une autre fonctionnalité.

Il était destiné à créer un tuple avec des références à des variables

Crée un tuple de références lvalue à ses arguments ou instances de std :: ignore.

Ceci est utile pour créer des n-uplets à la volée sans avoir à copier les variables car ce sont des références. Je prends juste l’exemple de cppreference pour un cas d’utilisation.

 bool operator<(const S& rhs) const { // compares n to rhs.n, // then s to rhs.s, // then d to rhs.d return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d); } 

Ici, les n-uplets sont créés mais ils ne copient pas les variables mais ont des références.

Maintenant, parce qu'ils contiennent des références, vous pouvez le "pirater" pour faire quelque chose comme ça

 int a,b,c; std::tie(a,b,c) = std::make_tuple(1,2,3); 

Il assigne les valeurs du tuple retourné à celui avec les références en lui-même.

Ceci est même sur cpprefence juste mentionné comme une "note"

std :: tie peut être utilisé pour décompresser un std :: pair car std :: tuple a une affectation de conversion à partir de paires

Donc, dans c ++ 11 n’était pas vraiment un moyen officiel d’atsortingbuer directement des valeurs, mais std::tie peut être utilisé comme cela, mais peut-être n’a-t-il jamais été conçu de cette manière.

Ils ont donc introduit la nouvelle "liaison structurée".

Que std::tie été conçu pour être utilisé de cette façon ou qu'il s'agisse d'un "hack" peut constituer un avis personnel, je suppose que les personnes qui ont présenté std::tie savent le mieux. Mais compte tenu du type de liaison structuré qui remplace std::tie dans ce cas, ils ont proposé une solution qui leur semble meilleure.