Skip to content

Commit f9f01e9

Browse files
committed
P1061R10 Structured Bindings can introduce a Pack
- Replace digits with numeral words in comment in example.
1 parent d017ce4 commit f9f01e9

File tree

4 files changed

+128
-21
lines changed

4 files changed

+128
-21
lines changed

source/declarations.tex

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,19 @@
6969
\end{bnf}
7070

7171
\begin{bnf}
72-
\nontermdef{attributed-identifier}\br
73-
identifier \opt{attribute-specifier-seq}
72+
\nontermdef{sb-identifier}\br
73+
\opt{\terminal{...}} identifier \opt{attribute-specifier-seq}
7474
\end{bnf}
7575

7676
\begin{bnf}
77-
\nontermdef{attributed-identifier-list}\br
78-
attributed-identifier\br
79-
attributed-identifier-list \terminal{,} attributed-identifier
77+
\nontermdef{sb-identifier-list}\br
78+
sb-identifier\br
79+
sb-identifier-list \terminal{,} sb-identifier
8080
\end{bnf}
8181

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

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

70207024
\pnum
70217025
A structured binding declaration introduces the \grammarterm{identifier}{s}
7022-
$\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc$
7026+
$\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc, \tcode{v}_{N-1}$
70237027
of the
7024-
\grammarterm{attributed-identifier-list} as names
7025-
of \defn{structured binding}{s}.
7028+
\grammarterm{sb-identifier-list} as names.
7029+
An \grammarterm{sb-identifier} that contains an ellipsis
7030+
introduces a structured binding pack\iref{temp.variadic}.
7031+
A \defn{structured binding} is either
7032+
an \grammarterm{sb-identifier} that does not contain an ellipsis or
7033+
an element of a structured binding pack.
70267034
The optional \grammarterm{attribute-specifier-seq} of
7027-
an \grammarterm{attributed-identifier}
7028-
appertains to the structured binding so introduced.
7035+
an \grammarterm{sb-identifier}
7036+
appertains to the associated structured bindings.
70297037
Let \cv{} denote the \grammarterm{cv-qualifier}{s} in
70307038
the \grammarterm{decl-specifier-seq} and
70317039
\placeholder{S} consist of the \grammarterm{storage-class-specifier}{s} of
@@ -7057,6 +7065,42 @@
70577065
\tcode{E} is never a reference type\iref{expr.prop}.
70587066
\end{note}
70597067

7068+
\pnum
7069+
The \defn{structured binding size} of \tcode{E}, as defined below,
7070+
is the number of structured bindings
7071+
that need to be introduced by the structured binding declaration.
7072+
If there is no structured binding pack,
7073+
then the number of elements in the \grammarterm{sb-identifier-list}
7074+
shall be equal to the structured binding size of \tcode{E}.
7075+
Otherwise, the number of non-pack elements shall be no more than
7076+
the structured binding size of \tcode{E};
7077+
the number of elements of the structured binding pack is
7078+
the structured binding size of \tcode{E} less
7079+
the number of non-pack elements in the\grammarterm{ sb-identifier-list}.
7080+
7081+
\pnum
7082+
Let $\textrm{SB}_i$ denote
7083+
the $i^\textrm{th}$ structured binding in the structured binding declaration
7084+
after expanding the structured binding pack, if any.
7085+
\begin{note}
7086+
If there is no structured binding pack,
7087+
then $\textrm{SB}_i$ denotes $\tcode{v}_i$.
7088+
\end{note}
7089+
\begin{example}
7090+
\begin{codeblock}
7091+
struct C { int x, y, z; };
7092+
7093+
template<class T>
7094+
void now_i_know_my() {
7095+
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}
7096+
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$
7097+
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}
7098+
auto [h, i, j, ...k] = C(); // OK, the pack \tcode{k} is empty
7099+
auto [l, m, n, o, ...p] = C(); // error: structured binding size is too small
7100+
}
7101+
\end{codeblock}
7102+
\end{example}
7103+
70607104
\pnum
70617105
If a structured binding declaration appears as a \grammarterm{condition},
70627106
the decision variable\iref{stmt.pre} of the condition is \exposid{e}.
@@ -7067,9 +7111,10 @@
70677111
the program is ill-formed.
70687112

70697113
\pnum
7070-
If \tcode{E} is an array type with element type \tcode{T}, the number
7071-
of elements in the \grammarterm{attributed-identifier-list} shall be equal to the
7072-
number of elements of \tcode{E}. Each $\tcode{v}_i$ is the name of an
7114+
If \tcode{E} is an array type with element type \tcode{T},
7115+
the structured binding size of \tcode{E} is equal to the
7116+
number of elements of \tcode{E}.
7117+
Each $\textrm{SB}_i$ is the name of an
70737118
lvalue that refers to the element $i$ of the array and whose type
70747119
is \tcode{T}; the referenced type is \tcode{T}.
70757120
\begin{note}
@@ -7080,6 +7125,19 @@
70807125
auto f() -> int(&)[2];
70817126
auto [ x, y ] = f(); // \tcode{x} and \tcode{y} refer to elements in a copy of the array return value
70827127
auto& [ xr, yr ] = f(); // \tcode{xr} and \tcode{yr} refer to elements in the array referred to by \tcode{f}'s return value
7128+
7129+
auto g() -> int(&)[4];
7130+
7131+
template<size_t N>
7132+
void h(int (&arr)[N]) {
7133+
auto [a, ...b, c] = arr; // \tcode{a} names the first element of the array, \tcode{b} is a pack referring to the second and
7134+
// third elements, and \tcode{c} names the fourth element
7135+
auto& [...e] = arr; // \tcode{e} is a pack referring to the four elements of the array
7136+
}
7137+
7138+
void call_h() {
7139+
h(g());
7140+
}
70837141
\end{codeblock}
70847142
\end{example}
70857143

@@ -7090,8 +7148,7 @@
70907148
the expression \tcode{std::tuple_size<E>::value}
70917149
shall be a well-formed integral constant expression
70927150
and
7093-
the number of elements in
7094-
the \grammarterm{attributed-identifier-list} shall be equal to the value of that
7151+
the structured binding size of \tcode{E} is equal to the value of that
70957152
expression.
70967153
Let \tcode{i} be an index prvalue of type \tcode{std::size_t}
70977154
corresponding to $\tcode{v}_i$.
@@ -7121,7 +7178,7 @@
71217178
\placeholder{S} \terminal{U$_i$ r$_i$ =} initializer \terminal{;}
71227179
\end{ncbnf}
71237180

7124-
Each $\tcode{v}_i$ is the name of an lvalue of type $\tcode{T}_i$
7181+
Each $\textrm{SB}_i$ is the name of an lvalue of type $\tcode{T}_i$
71257182
that refers to the object bound to $\tcode{r}_i$;
71267183
the referenced type is $\tcode{T}_i$.
71277184
The initialization of \exposid{e} and
@@ -7139,7 +7196,7 @@
71397196
well-formed when named as \tcode{\exposidnc{e}.\placeholder{name}}
71407197
in the context of the structured binding,
71417198
\tcode{E} shall not have an anonymous union member, and
7142-
the number of elements in the \grammarterm{attributed-identifier-list} shall be
7199+
the structured binding size of \tcode{E} is
71437200
equal to the number of non-static data members of \tcode{E}.
71447201
Designating the non-static data members of \tcode{E} as
71457202
$\tcode{m}_0$, $\tcode{m}_1$, $\tcode{m}_2, \dotsc$

source/expressions.tex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2844,6 +2844,9 @@
28442844
}
28452845
\end{codeblock}
28462846
\end{example}
2847+
2848+
\pnum
2849+
A fold expression is a pack expansion.
28472850
\indextext{expression!fold|)}%
28482851

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

source/preprocessor.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1895,7 +1895,7 @@
18951895
\defnxname{cpp_sized_deallocation} & \tcode{201309L} \\ \rowsep
18961896
\defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep
18971897
\defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep
1898-
\defnxname{cpp_structured_bindings} & \tcode{202403L} \\ \rowsep
1898+
\defnxname{cpp_structured_bindings} & \tcode{202411L} \\ \rowsep
18991899
\defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep
19001900
\defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep
19011901
\defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep

source/templates.tex

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,11 +2809,27 @@
28092809
\end{codeblock}
28102810
\end{example}
28112811

2812+
\pnum
2813+
A \defn{structured binding pack} is an \grammarterm{sb-identifier}
2814+
that introduces zero or more structured bindings\iref{dcl.struct.bind}.
2815+
\begin{example}
2816+
\begin{codeblock}
2817+
auto foo() -> int(&)[2];
2818+
2819+
template <class T>
2820+
void g() {
2821+
auto [...a] = foo(); // \tcode{a} is a structured binding pack containing two elements
2822+
auto [b, c, ...d] = foo(); // \tcode{d} is a structured binding pack containing zero elements
2823+
}
2824+
\end{codeblock}
2825+
\end{example}
2826+
28122827
\pnum
28132828
A \defn{pack} is
28142829
a template parameter pack,
28152830
a function parameter pack,
2816-
or an \grammarterm{init-capture} pack.
2831+
an \grammarterm{init-capture} pack, or
2832+
a structured binding pack.
28172833
The number of elements of a template parameter pack
28182834
or a function parameter pack
28192835
is the number of arguments provided for the parameter pack.
@@ -2976,7 +2992,14 @@
29762992
designating the variable introduced by
29772993
the $i^\text{th}$ \grammarterm{init-capture}
29782994
that resulted from instantiation of
2979-
the \grammarterm{init-capture} pack declaration.
2995+
the \grammarterm{init-capture} pack declaration;
2996+
otherwise
2997+
2998+
\item
2999+
if the pack is a structured binding pack,
3000+
the element is an \grammarterm{id-expression}
3001+
designating the $i^\textrm{th}$ structured binding in the pack
3002+
that resulted from the structured binding declaration.
29803003
\end{itemize}
29813004
When $N$ is zero, the instantiation of a pack expansion
29823005
does not alter the syntactic interpretation of the enclosing construct,
@@ -5304,6 +5327,28 @@
53045327
a structured binding declaration\iref{dcl.struct.bind} whose
53055328
\grammarterm{brace-or-equal-initializer} is type-dependent,
53065329
\item
5330+
associated by name lookup with a pack,
5331+
\begin{example}
5332+
\begin{codeblock}
5333+
struct C { };
5334+
5335+
void g(...); // \#1
5336+
5337+
template <typename T>
5338+
void f() {
5339+
C arr[1];
5340+
auto [...e] = arr;
5341+
g(e...); // calls \#2
5342+
}
5343+
5344+
void g(C); // \#2
5345+
5346+
int main() {
5347+
f<int>();
5348+
}
5349+
\end{codeblock}
5350+
\end{example}
5351+
\item
53075352
associated by name lookup with
53085353
an entity captured by copy\iref{expr.prim.lambda.capture}
53095354
in a \grammarterm{lambda-expression}
@@ -5481,6 +5526,8 @@
54815526
\keyword{sizeof} \terminal{...} \terminal{(} identifier \terminal{)}\br
54825527
fold-expression
54835528
\end{ncsimplebnf}
5529+
unless the \grammarterm{identifier} is a structured binding pack
5530+
whose initializer is not dependent.
54845531

54855532
\pnum
54865533
An expression of the form \tcode{\&}\grammarterm{qualified-id} where the

0 commit comments

Comments
 (0)