You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _articles/c++_auto.md
+176-2Lines changed: 176 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1049,11 +1049,185 @@ function(auto{expr});
1049
1049
1050
1050
## Structured binding pack (depuis C++26)
1051
1051
1052
-
Dans la continuité des [structured binding declaration](#structured-binding-declaration-depuis-c17), le C++26 ajoute la possibilité de d'extraire des éléments dans un [pack](/articles/c++/templates#pack) ([proposal](https://wg21.link/P1061R10), [approval](https://wg21.link/P1061R9/status)).
1052
+
Dans la continuité des [structured binding declaration](#structured-binding-declaration-depuis-c17), le C++26 ajoute la possibilité de d'extraire des éléments d'un [pack](/articles/c++/templates#pack) ([proposal](https://wg21.link/P1061R10), [approval](https://wg21.link/P1061R9/status)).
1053
1053
1054
1054
Cette fonctionnalité n'est [pas encore supportée par les compilateurs](https://en.cppreference.com/w/cpp/26) à l'heure où j'écris.
1055
+
On peut cependant la trouver en experimental sur Clang.
1055
1056
1056
-
{% wip %}
1057
+
Ce n'est pas une nouvelle fonctionnalité à proprement parler, il s'agit en fait d'une extension des [structured binding declaration](#structured-binding-declaration-depuis-c17)** leur permettant de supporter les [pack](/articles/c++/templates#pack).
1058
+
1059
+
{% highlight cpp linenos highlight_lines="4" %}
1060
+
auto container = std::tuple{1, 2, 3};
1061
+
1062
+
auto [x, y, z] = container;
1063
+
auto [...values] = container; // values contient les valeurs 1, 2 et 3
1064
+
{% endhighlight %}
1065
+
1066
+
Pour [rappel](/articles/c++/templates#pack), un pack est un outil de **metaprogrammation** fonctionnant dans le **contexte d'une template**.<br>
1067
+
Les *structured binding pack* sont donc utilisables **uniquement dans des fonctions templatées** (dans une "templated region"):
1068
+
1069
+
{% highlight cpp linenos highlight_lines="6" %}
1070
+
auto main() -> int
1071
+
{
1072
+
auto container = std::tuple{1, 2, 3};
1073
+
1074
+
[[maybe_unused]] auto [x, y, z] = container; // Ok
1075
+
[[maybe_unused]] auto [...values] = container; // error: pack declaration outside of template
1076
+
}
1077
+
{% endhighlight %}
1078
+
1079
+
Dans le contexte d'une template:
1080
+
{% highlight cpp linenos highlight_lines="1" %}
1081
+
template<classContainer>
1082
+
auto function(Container container) -> void
1083
+
{
1084
+
[[maybe_unused]] auto [...values] = container; // Ok
1085
+
}
1086
+
{% endhighlight %}
1087
+
1088
+
Ou écrit plus simplement:
1089
+
{% highlight cpp linenos %}
1090
+
auto function(auto container) -> void // Fonction template (le type du paramètre container est templaté)
1091
+
{
1092
+
[[maybe_unused]] auto [...values] = container; // Ok
1093
+
}
1094
+
{% endhighlight %}
1095
+
1096
+
> Ce sujet a levé beaucoup d'interrogations dans la [revision 9 du proposal](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1061r10.html#removing-packs-outside-of-templates) pour rendre les *structured binding pack* utilisables **dans des fonctions non templatées**. Impliquant qu'une notion d'"**implicit template region**" soit ajoutée au langage pour les supporter.
1097
+
>
1098
+
> Il a été décidé dans la revision 10 que la notion d'"implicit template region" serait **trop complexe à implémenter** dans les compilateurs et ne serait donc **pas ajouté**, limitant l'usage des *structured binding pack* aux contextes de templates.
1099
+
>
1100
+
> Petite anecdote: [Jason Rice a implémenté cette notion d'"implicit template region" dans le compilateur Clang](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1061r10.html#implementation-experience) avant que cette discussion ai lieu. Il a ensuite dû revenir en arrière et supprimer cette notion, disant que "Honnêtement, les contextes implicites de template ont grandement simplifié les choses, et une grande partie du code a été supprimée".
1101
+
1102
+
Pour poursuivre sur les différents usages de cette fonctionnalité, le pack n'est pas obligé de contenir tous les éléments du conteneur. Il est possible d'en décomposer quelques-uns avant ou après celui-ci.
1103
+
1104
+
{% highlight cpp linenos %}
1105
+
auto container = std::tuple{1, 2, 3};
1106
+
1107
+
auto [x, ...others] = container; // Ok: x contient 1; Et others contient 2 et 3
1108
+
auto [...others, z] = container; // Ok: z contient 3; Et others contient 1 et 2
1109
+
{% endhighlight %}
1110
+
1111
+
Le pack peut également être vide si tous les éléments sont déjà décomposés dans des variables à part.
1112
+
{% highlight cpp linenos %}
1113
+
auto container = std::tuple{1, 2, 3};
1114
+
1115
+
auto [x, y, z, ...others] = container; // Ok: others est vide
1116
+
auto [x, y, z, w, ...others] = container; // error: structured binding size is too small
1117
+
{% endhighlight %}
1118
+
1119
+
En revanche il ne peut pas y avoir plusieurs packs dans la même *structured binding declaration*.
1120
+
{% highlight cpp %}
1121
+
auto [...pack1, ...pack2] = container; // error: multiple packs in structured binding declaration
1122
+
{% endhighlight %}
1123
+
1124
+
### Exemples
1125
+
1126
+
Il n'est parfois pas très clair des possibilités qu'apporte qu'une telle fonctionnalité, c'est pourquoi je vous présente quelques exemples d'utilisation:
1127
+
1128
+
Une fonction ``print`` qui affiche une liste de valeurs de types variés:
1129
+
{% highlight cpp linenos highlight_lines="3" %}
1130
+
auto print(const auto& tuple) -> void
1131
+
{
1132
+
const auto& [...values] = tuple;
1133
+
(std::cout << ... << values) << "\n";
1134
+
}
1135
+
1136
+
auto main() -> int
1137
+
{
1138
+
auto tuple = std::make_tuple(1, 2, 3, "soleil");
1139
+
print(tuple);
1140
+
}
1141
+
{% endhighlight %}
1142
+
1143
+
{% highlight console %}
1144
+
123soleil
1145
+
{% endhighlight %}
1146
+
1147
+
> Ceci est un exemple, privilégiez la fonction [``std::print``](https://en.cppreference.com/w/cpp/io/print) dans vos projets.
1148
+
1149
+
Une fonction de print un peu plus poussée qui affiche les variables membres d'une structure passée en paramètre:
1150
+
{% highlight cpp linenos highlight_lines="10" %}
1151
+
struct Data
1152
+
{
1153
+
int id;
1154
+
double number;
1155
+
std::string name;
1156
+
};
1157
+
1158
+
auto printFields(const auto& object, const auto& tupleLike) -> void
0 commit comments