Files
cppdraft_translate/cppdraft/stmt/expand.md
2025-10-25 03:02:53 +03:00

8.1 KiB
Raw Blame History

[stmt.expand]

8 Statements [stmt]

8.7 Expansion statements [stmt.expand]

1

#

Expansion statements specify repeated instantiations ([temp.decls.general]) of their substatement.

expansion-statement:
template for (init-statementopt for-range-declaration :expansion-initializer ) compound-statement

expansion-initializer:
expression
expansion-init-list

expansion-init-list:
{ expression-listopt }

2

#

The compound-statement of an expansion-statement is a control-flow-limited statement ([stmt.label]).

3

#

For an expression E, let the expressionsbegin-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.

4

#

An expansion statement is

an enumerating expansion statement if its expansion-initializer is of the form expansion-init-list;

otherwise, an iterating expansion statement if its expansion-initializer is an expansion-iterable expression;

otherwise, a destructuring expansion statement.

5

#

An expansion statement S is equivalent to a compound-statement containing 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-statementS0 ⋮ SN−1} where N is the number of elements in the expression-list,Si is{for-range-declaration = Ei; compound-statement} and Ei is the ith element of the expression-list.

Otherwise, if S is an iterating expansion statement, S is equivalent to:{init-statementstatic constexpr auto&& range = expansion-initializer; static constexpr auto begin = begin-expr; // see [stmt.ranged]static constexpr auto end = end-expr; // see [stmt.ranged]S0 ⋮ SN−1} 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; // distance from begin to end}() and Si 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-statementconstexpropt auto&& [u0, u1, …, uN−1] = expansion-initializer; S0 ⋮ SN−1} where N is the structured binding size of the type of the expansion-initializer and Si is{for-range-declaration = ui; compound-statement} The keyword constexpr is present in the declaration of u0,u1,…,uN−1 if and only ifconstexpr is one of the decl-specifiers of the decl-specifier-seq of the for-range-declaration.

6

#

[Example 1: consteval int f(auto const&... Containers) {int result = 0; template for (auto const& c : {Containers...}) { // OK, enumerating expansion statement 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]

7

#

[Example 2: consteval int f() {constexpr std::array<int, 3> arr {1, 2, 3}; int result = 0; template for (constexpr int s : arr) { // OK, iterating expansion statement result += sizeof(char[s]); }return result;}static_assert(f() == 6); — end example]

8

#

[Example 3: struct S {int i; short s;};

consteval long f(S s) {long result = 0; template for (auto x : s) { // OK, destructuring expansion statement result += sizeof(x); }return result;}static_assert(f(S{}) == sizeof(int) + sizeof(short)); — end example]