From Jason Turner

[stmt.expand]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpvdqvda1a/{from.md → to.md} +184 -0
tmp/tmpvdqvda1a/{from.md → to.md} RENAMED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Expansion statements <a id="stmt.expand">[[stmt.expand]]</a>
2
+
3
+ Expansion statements specify repeated instantiations
4
+ [[temp.decls.general]] of their substatement.
5
+
6
+ ``` bnf
7
+ expansion-statement:
8
+ template for '('
9
+ init-statementₒₚₜ for-range-declaration ':'
10
+ expansion-initializer ')' compound-statement
11
+ ```
12
+
13
+ ``` bnf
14
+ expansion-initializer:
15
+ expression
16
+ expansion-init-list
17
+ ```
18
+
19
+ ``` bnf
20
+ expansion-init-list:
21
+ '{' expression-listₒₚₜ '}'
22
+ ```
23
+
24
+ The *compound-statement* of an *expansion-statement* is a
25
+ control-flow-limited statement [[stmt.label]].
26
+
27
+ For an expression `E`, let the expressions *`begin-expr`* and
28
+ *`end-expr`* be determined as specified in  [[stmt.ranged]]. An
29
+ expression is *expansion-iterable* if it does not have array type and
30
+ either
31
+
32
+ - *`begin-expr`* and *`end-expr`* are of the form `E.begin()` and
33
+ `E.end()`, or
34
+ - argument-dependent lookups for `begin(E)` and for `end(E)` each find
35
+ at least one function or function template.
36
+
37
+ An expansion statement is
38
+
39
+ - an *enumerating expansion statement* if its *expansion-initializer* is
40
+ of the form *expansion-init-list*;
41
+ - otherwise, an *iterating expansion statement* if its
42
+ *expansion-initializer* is an expansion-iterable expression;
43
+ - otherwise, a *destructuring expansion statement*.
44
+
45
+ An expansion statement S is equivalent to a *compound-statement*
46
+ containing instantiations of the *for-range-declaration* (including its
47
+ implied initialization), together with the compound-statement of S, as
48
+ follows:
49
+
50
+ - If S is an enumerating expansion statement, S is equivalent to:
51
+ ``` cpp
52
+ {
53
+ init-statement
54
+ S₀
55
+
56
+ S_N-1}
57
+ }
58
+ ```
59
+
60
+ where N is the number of elements in the *expression-list*, Sᵢ is
61
+ ``` cpp
62
+ {
63
+ for-range-declaration = Eᵢ;
64
+ compound-statement
65
+ }
66
+ ```
67
+
68
+ and Eᵢ is the iᵗʰ element of the *expression-list*.
69
+ - Otherwise, if S is an iterating expansion statement, S is equivalent
70
+ to:
71
+ ``` cpp
72
+ {
73
+ init-statement
74
+ static constexpr auto&& range = expansion-initializer;
75
+ static constexpr auto begin = begin-expr; // see [stmt.ranged]
76
+ static constexpr auto end = end-expr; // see [stmt.ranged]
77
+
78
+ S₀
79
+
80
+ S_N-1}
81
+ }
82
+ ```
83
+
84
+ where N is the result of evaluating the expression
85
+ ``` cpp
86
+ []consteval {
87
+ std::ptrdiff_t result = 0;
88
+ for (auto i = begin; i != end; ++i, ++result);
89
+ return result; // distance from begin to end
90
+ }()
91
+ ```
92
+
93
+ and Sᵢ is
94
+ ``` cpp
95
+ {
96
+ static constexpr auto iter = begin + i;
97
+ for-range-declaration = *iter;
98
+ compound-statement
99
+ }
100
+ ```
101
+
102
+ The variables *`range`*, *`begin`*, *`end`*, and *`iter`* are defined
103
+ for exposition only.
104
+ \[*Note 1*: The instantiation is ill-formed if *`range`* is not a
105
+ constant expression [[expr.const]]. — *end note*]
106
+ - Otherwise, S is a destructuring expansion statement and S is
107
+ equivalent to:
108
+ ``` cpp
109
+ {
110
+ init-statement
111
+ \opt{constexpr} auto&& [u₀, u₁, …, u_N-1}] = expansion-initializer;
112
+ S₀
113
+
114
+ S_N-1}
115
+ }
116
+ ```
117
+
118
+ where N is the structured binding size of the type of the
119
+ *expansion-initializer* and Sᵢ is
120
+ ``` cpp
121
+ {
122
+ for-range-declaration = uᵢ;
123
+ compound-statement
124
+ }
125
+ ```
126
+
127
+ The keyword `constexpr` is present in the declaration of
128
+ $u_{0}, u_{1}, \dotsc, u_{N-1}$ if and only if `constexpr` is one of
129
+ the *decl-specifier*s of the *decl-specifier-seq* of the
130
+ *for-range-declaration*.
131
+
132
+ [*Example 1*:
133
+
134
+ ``` cpp
135
+ consteval int f(auto const&... Containers) {
136
+ int result = 0;
137
+ template for (auto const& c : {Containers...}) { // OK, enumerating expansion statement
138
+ result += c[0];
139
+ }
140
+ return result;
141
+ }
142
+ constexpr int c1[] = {1, 2, 3};
143
+ constexpr int c2[] = {4, 3, 2, 1};
144
+ static_assert(f(c1, c2) == 5);
145
+ ```
146
+
147
+ — *end example*]
148
+
149
+ [*Example 2*:
150
+
151
+ ``` cpp
152
+ consteval int f() {
153
+ constexpr std::array<int, 3> arr {1, 2, 3};
154
+ int result = 0;
155
+ template for (constexpr int s : arr) { // OK, iterating expansion statement
156
+ result += sizeof(char[s]);
157
+ }
158
+ return result;
159
+ }
160
+ static_assert(f() == 6);
161
+ ```
162
+
163
+ — *end example*]
164
+
165
+ [*Example 3*:
166
+
167
+ ``` cpp
168
+ struct S {
169
+ int i;
170
+ short s;
171
+ };
172
+
173
+ consteval long f(S s) {
174
+ long result = 0;
175
+ template for (auto x : s) { // OK, destructuring expansion statement
176
+ result += sizeof(x);
177
+ }
178
+ return result;
179
+ }
180
+ static_assert(f(S{}) == sizeof(int) + sizeof(short));
181
+ ```
182
+
183
+ — *end example*]
184
+