web-dev-qa-db-fra.com

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

La norme C++ 17 introduit une nouvelle fonctionnalité des liaisons structurées , qui avait été initialement proposée en 2015 et dont l'apparence syntaxique a été largement discutée plus tard.

Certaines utilisations viennent à l’esprit dès que vous parcourez la documentation.

Décomposition des agrégats

Déclarons un tuple:

std::Tuple<int, std::string> 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;

qui équivaut à:

auto i = std::get<0>(t);
auto s = std::get<1>(t);

ou

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

Les références aux éléments 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é.

15
Sergey

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 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 = s.x;
    auto y = s.y;
    (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, 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 de cas que vous avez déjà mentionné.


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

#include <map>
#include <iostream>

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

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<N> pour les structures - voir magic_get'S G&EACUTE;N&EACUTE;R&EACUTE; AUTOMATIQUEMENT core17_generated.hpp . Ceci est utile car il fournit une forme primitive de réflexion statique (par exemple, une itération sur tous les membres d’un struct).

9
Vittorio Romeo

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 restent un mystère non résolu. Esp. étant donné que le document est co-écrit par Bjarne, qui n'est généralement pas connu pour introduire des fonctionnalités ayant une applicabilité aussi étroite.

1
Marc Mutz - mmutz