Skip to content

Commit dabeefc

Browse files
jensmaurertkoeppe
authored andcommitted
P1061R10 Structured Bindings can introduce a Pack
Editorial notes: * Replace digits with numeral words in comment in example.
1 parent f3ec6d7 commit dabeefc

File tree

4 files changed

+129
-23
lines changed

4 files changed

+129
-23
lines changed

source/declarations.tex

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,19 @@
6868
\end{bnf}
6969

7070
\begin{bnf}
71-
\nontermdef{attributed-identifier}\br
72-
identifier \opt{attribute-specifier-seq}
71+
\nontermdef{sb-identifier}\br
72+
\opt{\terminal{...}} identifier \opt{attribute-specifier-seq}
7373
\end{bnf}
7474

7575
\begin{bnf}
76-
\nontermdef{attributed-identifier-list}\br
77-
attributed-identifier\br
78-
attributed-identifier-list \terminal{,} attributed-identifier
76+
\nontermdef{sb-identifier-list}\br
77+
sb-identifier\br
78+
sb-identifier-list \terminal{,} sb-identifier
7979
\end{bnf}
8080

8181
\begin{bnf}
8282
\nontermdef{structured-binding-declaration}\br
83-
\opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} attributed-identifier-list \terminal{]}
83+
\opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} sb-identifier-list \terminal{]}
8484
\end{bnf}
8585

8686
\begin{bnf}
@@ -218,6 +218,10 @@
218218
\tcode{thread_local},
219219
\tcode{auto}\iref{dcl.spec.auto}, or
220220
a \grammarterm{cv-qualifier}.
221+
The declaration shall contain at most one \grammarterm{sb-identifier}
222+
whose \grammarterm{identifier} is preceded by an ellipsis.
223+
If the declaration contains any such \grammarterm{sb-identifier},
224+
it shall declare a templated entity\iref{temp.pre}.
221225
\begin{example}
222226
\begin{codeblock}
223227
template<class T> concept C = true;
@@ -7040,13 +7044,17 @@
70407044

70417045
\pnum
70427046
A structured binding declaration introduces the \grammarterm{identifier}{s}
7043-
$\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc$
7047+
$\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc, \tcode{v}_{N-1}$
70447048
of the
7045-
\grammarterm{attributed-identifier-list} as names
7046-
of \defn{structured binding}{s}.
7049+
\grammarterm{sb-identifier-list} as names.
7050+
An \grammarterm{sb-identifier} that contains an ellipsis
7051+
introduces a structured binding pack\iref{temp.variadic}.
7052+
A \defn{structured binding} is either
7053+
an \grammarterm{sb-identifier} that does not contain an ellipsis or
7054+
an element of a structured binding pack.
70477055
The optional \grammarterm{attribute-specifier-seq} of
7048-
an \grammarterm{attributed-identifier}
7049-
appertains to the structured binding so introduced.
7056+
an \grammarterm{sb-identifier}
7057+
appertains to the associated structured bindings.
70507058
Let \cv{} denote the \grammarterm{cv-qualifier}{s} in
70517059
the \grammarterm{decl-specifier-seq} and
70527060
\placeholder{S} consist of
@@ -7080,6 +7088,42 @@
70807088
\tcode{E} is never a reference type\iref{expr.prop}.
70817089
\end{note}
70827090

7091+
\pnum
7092+
The \defn{structured binding size} of \tcode{E}, as defined below,
7093+
is the number of structured bindings
7094+
that need to be introduced by the structured binding declaration.
7095+
If there is no structured binding pack,
7096+
then the number of elements in the \grammarterm{sb-identifier-list}
7097+
shall be equal to the structured binding size of \tcode{E}.
7098+
Otherwise, the number of non-pack elements shall be no more than
7099+
the structured binding size of \tcode{E};
7100+
the number of elements of the structured binding pack is
7101+
the structured binding size of \tcode{E} less
7102+
the number of non-pack elements in the\grammarterm{sb-identifier-list}.
7103+
7104+
\pnum
7105+
Let $\textrm{SB}_i$ denote
7106+
the $i^\textrm{th}$ structured binding in the structured binding declaration
7107+
after expanding the structured binding pack, if any.
7108+
\begin{note}
7109+
If there is no structured binding pack,
7110+
then $\textrm{SB}_i$ denotes $\tcode{v}_i$.
7111+
\end{note}
7112+
\begin{example}
7113+
\begin{codeblock}
7114+
struct C { int x, y, z; };
7115+
7116+
template<class T>
7117+
void now_i_know_my() {
7118+
auto [a, b, c] = C(); // OK, $\textrm{SB}_0$ is \tcode{a}, $\textrm{SB}_1$ is \tcode{b}, and $\textrm{SB}_2$ is \tcode{c}
7119+
auto [d, ...e] = C(); // OK, $\textrm{SB}_0$ is \tcode{d}, the pack \tcode{e} $(\tcode{v}_1)$ contains two structured bindings: $\textrm{SB}_1$ and $\textrm{SB}_2$
7120+
auto [...f, g] = C(); // OK, the pack \tcode{f} $(\tcode{v}_0)$ contains two structured bindings: $\textrm{SB}_0$ and $\textrm{SB}_1$, and $\textrm{SB}_2$ is \tcode{g}
7121+
auto [h, i, j, ...k] = C(); // OK, the pack \tcode{k} is empty
7122+
auto [l, m, n, o, ...p] = C(); // error: structured binding size is too small
7123+
}
7124+
\end{codeblock}
7125+
\end{example}
7126+
70837127
\pnum
70847128
If a structured binding declaration appears as a \grammarterm{condition},
70857129
the decision variable\iref{stmt.pre} of the condition is \exposid{e}.
@@ -7090,9 +7134,10 @@
70907134
the program is ill-formed.
70917135

70927136
\pnum
7093-
If \tcode{E} is an array type with element type \tcode{T}, the number
7094-
of elements in the \grammarterm{attributed-identifier-list} shall be equal to the
7095-
number of elements of \tcode{E}. Each $\tcode{v}_i$ is the name of an
7137+
If \tcode{E} is an array type with element type \tcode{T},
7138+
the structured binding size of \tcode{E} is equal to the
7139+
number of elements of \tcode{E}.
7140+
Each $\textrm{SB}_i$ is the name of an
70967141
lvalue that refers to the element $i$ of the array and whose type
70977142
is \tcode{T}; the referenced type is \tcode{T}.
70987143
\begin{note}
@@ -7103,6 +7148,19 @@
71037148
auto f() -> int(&)[2];
71047149
auto [ x, y ] = f(); // \tcode{x} and \tcode{y} refer to elements in a copy of the array return value
71057150
auto& [ xr, yr ] = f(); // \tcode{xr} and \tcode{yr} refer to elements in the array referred to by \tcode{f}'s return value
7151+
7152+
auto g() -> int(&)[4];
7153+
7154+
template<size_t N>
7155+
void h(int (&arr)[N]) {
7156+
auto [a, ...b, c] = arr; // \tcode{a} names the first element of the array, \tcode{b} is a pack referring to the second and
7157+
// third elements, and \tcode{c} names the fourth element
7158+
auto& [...e] = arr; // \tcode{e} is a pack referring to the four elements of the array
7159+
}
7160+
7161+
void call_h() {
7162+
h(g());
7163+
}
71067164
\end{codeblock}
71077165
\end{example}
71087166

@@ -7113,8 +7171,7 @@
71137171
the expression \tcode{std::tuple_size<E>::value}
71147172
shall be a well-formed integral constant expression
71157173
and
7116-
the number of elements in
7117-
the \grammarterm{attributed-identifier-list} shall be equal to the value of that
7174+
the structured binding size of \tcode{E} is equal to the value of that
71187175
expression.
71197176
Let \tcode{i} be an index prvalue of type \tcode{std::size_t}
71207177
corresponding to $\tcode{v}_i$.
@@ -7144,7 +7201,7 @@
71447201
\placeholder{S} \terminal{U$_i$ r$_i$ =} initializer \terminal{;}
71457202
\end{ncbnf}
71467203

7147-
Each $\tcode{v}_i$ is the name of an lvalue of type $\tcode{T}_i$
7204+
Each $\textrm{SB}_i$ is the name of an lvalue of type $\tcode{T}_i$
71487205
that refers to the object bound to $\tcode{r}_i$;
71497206
the referenced type is $\tcode{T}_i$.
71507207
The initialization of \exposid{e} and
@@ -7162,12 +7219,12 @@
71627219
well-formed when named as \tcode{\exposidnc{e}.\placeholder{name}}
71637220
in the context of the structured binding,
71647221
\tcode{E} shall not have an anonymous union member, and
7165-
the number of elements in the \grammarterm{attributed-identifier-list} shall be
7222+
the structured binding size of \tcode{E} is
71667223
equal to the number of non-static data members of \tcode{E}.
71677224
Designating the non-static data members of \tcode{E} as
71687225
$\tcode{m}_0$, $\tcode{m}_1$, $\tcode{m}_2, \dotsc$
71697226
(in declaration order),
7170-
each $\tcode{v}_i$ is the
7227+
each $\textrm{SB}_i$ is the
71717228
name of an lvalue that refers to the member \tcode{m}$_i$ of \exposid{e} and
71727229
whose type is
71737230
that of \tcode{\exposidnc{e}.$\tcode{m}_i$}\iref{expr.ref};

source/expressions.tex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2864,6 +2864,9 @@
28642864
}
28652865
\end{codeblock}
28662866
\end{example}
2867+
2868+
\pnum
2869+
A fold expression is a pack expansion.
28672870
\indextext{expression!fold|)}%
28682871

28692872
\rSec2[expr.prim.req]{Requires expressions}

source/preprocessor.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1905,7 +1905,7 @@
19051905
\defnxname{cpp_sized_deallocation} & \tcode{201309L} \\ \rowsep
19061906
\defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep
19071907
\defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep
1908-
\defnxname{cpp_structured_bindings} & \tcode{202403L} \\ \rowsep
1908+
\defnxname{cpp_structured_bindings} & \tcode{202411L} \\ \rowsep
19091909
\defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep
19101910
\defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep
19111911
\defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep

source/templates.tex

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2840,11 +2840,27 @@
28402840
\end{codeblock}
28412841
\end{example}
28422842

2843+
\pnum
2844+
A \defn{structured binding pack} is an \grammarterm{sb-identifier}
2845+
that introduces zero or more structured bindings\iref{dcl.struct.bind}.
2846+
\begin{example}
2847+
\begin{codeblock}
2848+
auto foo() -> int(&)[2];
2849+
2850+
template <class T>
2851+
void g() {
2852+
auto [...a] = foo(); // \tcode{a} is a structured binding pack containing two elements
2853+
auto [b, c, ...d] = foo(); // \tcode{d} is a structured binding pack containing zero elements
2854+
}
2855+
\end{codeblock}
2856+
\end{example}
2857+
28432858
\pnum
28442859
A \defn{pack} is
28452860
a template parameter pack,
28462861
a function parameter pack,
2847-
or an \grammarterm{init-capture} pack.
2862+
an \grammarterm{init-capture} pack, or
2863+
a structured binding pack.
28482864
The number of elements of a template parameter pack
28492865
or a function parameter pack
28502866
is the number of arguments provided for the parameter pack.
@@ -2999,15 +3015,21 @@
29993015
designating the $i^\text{th}$ function parameter
30003016
that resulted from instantiation of
30013017
the function parameter pack declaration;
3002-
otherwise
30033018

30043019
\item
30053020
if the pack is an \grammarterm{init-capture} pack,
30063021
the element is an \grammarterm{id-expression}
30073022
designating the variable introduced by
30083023
the $i^\text{th}$ \grammarterm{init-capture}
30093024
that resulted from instantiation of
3010-
the \grammarterm{init-capture} pack declaration.
3025+
the \grammarterm{init-capture} pack declaration;
3026+
otherwise
3027+
3028+
\item
3029+
if the pack is a structured binding pack,
3030+
the element is an \grammarterm{id-expression}
3031+
designating the $i^\textrm{th}$ structured binding in the pack
3032+
that resulted from the structured binding declaration.
30113033
\end{itemize}
30123034
When $N$ is zero, the instantiation of a pack expansion
30133035
does not alter the syntactic interpretation of the enclosing construct,
@@ -5338,6 +5360,28 @@
53385360
a structured binding declaration\iref{dcl.struct.bind} whose
53395361
\grammarterm{brace-or-equal-initializer} is type-dependent,
53405362
\item
5363+
associated by name lookup with a pack,
5364+
\begin{example}
5365+
\begin{codeblock}
5366+
struct C { };
5367+
5368+
void g(...); // \#1
5369+
5370+
template <typename T>
5371+
void f() {
5372+
C arr[1];
5373+
auto [...e] = arr;
5374+
g(e...); // calls \#2
5375+
}
5376+
5377+
void g(C); // \#2
5378+
5379+
int main() {
5380+
f<int>();
5381+
}
5382+
\end{codeblock}
5383+
\end{example}
5384+
\item
53415385
associated by name lookup with
53425386
an entity captured by copy\iref{expr.prim.lambda.capture}
53435387
in a \grammarterm{lambda-expression}
@@ -5522,6 +5566,8 @@
55225566
\keyword{sizeof} \terminal{...} \terminal{(} identifier \terminal{)}\br
55235567
fold-expression
55245568
\end{ncsimplebnf}
5569+
unless the \grammarterm{identifier} is a structured binding pack
5570+
whose initializer is not dependent.
55255571

55265572
\pnum
55275573
A \grammarterm{noexcept-expression}\iref{expr.unary.noexcept}

0 commit comments

Comments
 (0)