Quels sont les cas d’utilisation pour les liaisons structurées?

La norme C ++ 17 introduit une nouvelle fonctionnalité de liaisons structurées , initialement proposée en 2015 et dont l’aspect syntaxique a été largement discuté plus tard.

Certaines utilisations viennent à l’esprit lorsque vous parcourez la documentation.

Décomposition des agrégats

Déclarons un tuple:

std::tuple t(42, "foo"); 

Des copies élémentaires nommées peuvent être facilement obtenues avec des liaisons structurées sur une seule ligne:

 auto [i, s] = t; 

ce qui équivaut à:

 auto i = std::get(t); auto s = std::get(t); 

ou

 int i; std::ssortingng s; std::tie(i, s) = t; 

Des références aux éléments du tuple peuvent également être obtenues sans douleur:

 auto& [ir, sr] = t; const auto& [icr, scr] = t; 

Nous pouvons donc utiliser des tableaux ou des structures / classes dont tous les membres sont publics.

Valeurs de retour multiples

Un moyen pratique d’obtenir plusieurs valeurs de retour d’une fonction découle immédiatement de ce qui précède.

Quoi d’autre?

Pouvez-vous fournir d’autres cas d’utilisation, peut-être moins évidents, pour les liaisons structurées? Sinon, comment peuvent-ils améliorer la lisibilité ou même les performances du code C ++?

Remarques

Comme mentionné dans les commentaires, certaines fonctionnalités ne sont pas implémentées dans les liaisons structurées. Ils ne sont pas variadiques et leur syntaxe ne permet pas d’ignorer explicitement les membres de l’agrégat. Ici, on peut trouver une discussion sur la variadicité.

Pouvez-vous fournir d’autres cas d’utilisation, peut-être moins évidents, pour les liaisons structurées? Sinon, comment peuvent-ils améliorer la lisibilité ou même les performances du code C ++?

Plus généralement, vous pouvez l’utiliser pour (laissez-moi dire) décompresser une structure et en remplir un ensemble de variables:

 struct S { int x = 0; int y = 1; }; int main() { S s{}; auto [ x, y ] = s; (void)x, void(y); } 

L’inverse aurait été:

 struct S { int x = 0; int y = 1; }; int main() { S s{}; auto x = sx; auto y = sy; (void)x, void(y); } 

La même chose est possible avec les tableaux:

 int main() { const int a[2] = { 0, 1 }; auto [ x, y ] = a; (void)x, void(y); } 

Quoi qu’il en soit, car cela fonctionne également lorsque vous renvoyez la structure ou le tableau d’une fonction, vous pouvez probablement affirmer que ces exemples appartiennent au même ensemble d’observations que vous avez déjà mentionné.


Un autre bon exemple mentionné dans les commentaires sur la réponse de @TobiasRibizel est la possibilité de parcourir les conteneurs et de décompresser facilement le contenu.
A titre d’exemple basé sur std::map :

 #include  #include  int main() { std::map m = {{ 0, 1 }, { 2, 3 }}; for(auto &[key, value]: m) { std::cout << key << ": " << value << std::endl; } } 

Pouvez-vous fournir d’autres cas d’utilisation, peut-être moins évidents, pour les liaisons structurées?

Ils peuvent être utilisés pour implémenter get pour les structures – voir magic_get , généré automatiquement par core17_generated.hpp . Ceci est utile car il fournit une forme primitive de reflection statique (par exemple, itérer sur tous les membres d’une struct ) .

Sauf preuve contraire, je pense que les liaisons structurées ne sont qu’un moyen de traiter les API héritées. IMHO, les API qui requièrent SB auraient dû être corrigées à la place.

Donc, au lieu de

 auto p = map.equal_range(k); for (auto it = p.first; it != p.second; ++it) doSomethingWith(it->first, it->second); 

nous devrions pouvoir écrire

 for (auto &e : map.equal_range(k)) doSomethingWith(e.key, e.value); 

Au lieu de

 auto r = map.insert({k, v}); if (!r.second) *r.first = v; 

nous devrions pouvoir écrire

 auto r = map.insert({k, v}); if (!r) r = v; 

etc.

Bien sûr, quelqu’un trouvera un usage intelligent à un moment donné, mais pour moi, après un an de connaissances à leur sujet, ils restnt un mystère non résolu. Esp. étant donné que l’article est co-écrit par Bjarne, qui n’est généralement pas connu pour introduire des fonctionnalités ayant une applicabilité aussi étroite.