[stmt.expand] (original) (raw)
8 Statements [stmt]
8.7 Expansion statements [stmt.expand]
For an expression E, let the expressions_begin-expr_ and end-expr be determined as specified in [stmt.ranged].
An expression is expansion-iterable if it does not have array type and either
- begin-expr and end-expr are of the formE.begin() and E.end(), or
- argument-dependent lookups for begin(E) and for end(E)each find at least one function or function template.
An expansion statement is
- an enumerating expansion statement if its expansion-initializeris of the form expansion-init-list;
- otherwise, an iterating expansion statement if its expansion-initializeris an expansion-iterable expression;
- otherwise, a destructuring expansion statement.
An expansion statement S is equivalent to a compound-statementcontaining instantiations of the for-range-declaration(including its implied initialization), together with the compound-statement of S, as follows:
- If S is an enumerating expansion statement, S is equivalent to:{ init-statement ⋮ } where N is the number of elements in the expression-list, is{ for-range-declaration = ;compound-statement } and is the element of the expression-list.
- Otherwise, if S is an iterating expansion statement, S is equivalent to:{ init-statement static constexpr auto&& range = expansion-initializer;static constexpr auto begin = begin-expr; static constexpr auto end = end-expr; ⋮ } where N is the result of evaluating the expression[] consteval { std::ptrdiff_t result = 0;for (auto i = begin; i != end; ++i, ++result);return result; }() and is{ static constexpr auto iter = begin + i;for-range-declaration = *iter;compound-statement }
The variables range, begin, end, and iter_are defined for exposition only.
[_Note 1:
The instantiation is ill-formed if _range_is not a constant expression ([expr.const]).
— _end note_] - Otherwise, S is a destructuring expansion statement and S is equivalent to:{ init-statement constexpr auto&& [, , …, ] = expansion-initializer; ⋮ } where N is the structured binding size of the type of the expansion-initializer and is{ for-range-declaration = ;compound-statement }
[Example 1: consteval int f(auto const&... Containers) { int result = 0;template for (auto const& c : {Containers...}) { result += c[0];} return result;} constexpr int c1[] = {1, 2, 3};constexpr int c2[] = {4, 3, 2, 1};static_assert(f(c1, c2) == 5); — _end example_]
[Example 2: consteval int f() { constexpr std::array<int, 3> arr {1, 2, 3};int result = 0;template for (constexpr int s : arr) { result += sizeof(char[s]);} return result;} static_assert(f() == 6); — _end example_]
[Example 3: struct S { int i;short s;};consteval long f(S s) { long result = 0;template for (auto x : s) { result += sizeof(x);} return result;} static_assert(f(S{}) == sizeof(int) + sizeof(short)); — _end example_]