[stmt.expand]

# 8 Statements [[stmt]](./#stmt)

## 8.7 Expansion statements [stmt.expand]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L790)

Expansion statements specify repeated instantiations ([[temp.decls.general]](temp.decls.general "13.7.1 General"))
of their substatement[.](#1.sentence-1)

[expansion-statement:](#nt:expansion-statement "8.7 Expansion statements [stmt.expand]")  
template for ([*init-statement*](stmt.pre#nt:init-statement "8.1 Preamble [stmt.pre]")opt [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") :[*expansion-initializer*](#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]") ) [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")

[expansion-initializer:](#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]")  
[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")  
[*expansion-init-list*](#nt:expansion-init-list "8.7 Expansion statements [stmt.expand]")

[expansion-init-list:](#nt:expansion-init-list "8.7 Expansion statements [stmt.expand]")  
{ [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt }

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L812)

The [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of an [*expansion-statement*](#nt:expansion-statement "8.7 Expansion statements [stmt.expand]") is a control-flow-limited statement ([[stmt.label]](stmt.label "8.2 Label"))[.](#2.sentence-1)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L816)

For an expression E, let the expressions*begin-expr* and *end-expr* be determined as specified in [[stmt.ranged]](stmt.ranged "8.6.5 The range-based for statement")[.](#3.sentence-1)

An expression is [*expansion-iterable*](#def:expansion-iterable "8.7 Expansion statements [stmt.expand]") if it does not have array type and either

- [(3.1)](#3.1)

*begin-expr* and *end-expr* are of the formE.begin() and E.end(), or

- [(3.2)](#3.2)

argument-dependent lookups for begin(E) and for end(E) each find at least one function or function template[.](#3.sentence-2)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L829)

An expansion statement is

- [(4.1)](#4.1)

an [*enumerating expansion statement*](#def:expansion_statement,enumerating "8.7 Expansion statements [stmt.expand]") if its [*expansion-initializer*](#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]") is of the form [*expansion-init-list*](#nt:expansion-init-list "8.7 Expansion statements [stmt.expand]");

- [(4.2)](#4.2)

otherwise, an [*iterating expansion statement*](#def:expansion_statement,iterating "8.7 Expansion statements [stmt.expand]") if its [*expansion-initializer*](#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]") is an expansion-iterable expression;

- [(4.3)](#4.3)

otherwise, a [*destructuring expansion statement*](#def:expansion_statement,destructuring "8.7 Expansion statements [stmt.expand]")[.](#4.sentence-1)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L842)

An expansion statement S is equivalent to a [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") containing instantiations of the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") (including its implied initialization),
together with the compound-statement of S, as follows:

- [(5.1)](#5.1)

If S is an enumerating expansion statement, S is equivalent to:{[*init-statement*](stmt.pre#nt:init-statement "8.1 Preamble [stmt.pre]")S0 ⋮ SNâ1} where N is the number of elements in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]"),Si is{[*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") = Ei; [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")} and Ei is the ith element of the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]").

- [(5.2)](#5.2)

Otherwise, if S is an iterating expansion statement, S is equivalent to:{[*init-statement*](stmt.pre#nt:init-statement "8.1 Preamble [stmt.pre]")static constexpr auto&& *range* = [*expansion-initializer*](#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]"); static constexpr auto *begin* = *begin-expr*; // see [[stmt.ranged]](stmt.ranged "8.6.5 The range-based for statement")static constexpr auto *end* = *end-expr*; // see [[stmt.ranged]](stmt.ranged "8.6.5 The range-based for statement")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*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") = **iter*; [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")}
   The variables *range*, *begin*, *end*, and *iter* are defined for exposition only[.](#5.2.sentence-2)
  [*Note [1](#note-1)*:
  The instantiation is ill-formed if *range* is not a constant expression ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#5.2.sentence-3)
 â *end note*]

- [(5.3)](#5.3)

Otherwise, S is a destructuring expansion statement and S is equivalent to:{[*init-statement*](stmt.pre#nt:init-statement "8.1 Preamble [stmt.pre]")constexpropt auto&& [u0, u1, …, uNâ1] = [*expansion-initializer*](#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]"); S0 ⋮ SNâ1} where N is the structured binding size of the type
of the [*expansion-initializer*](#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]") and Si is{[*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") = ui; [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")}
   The keyword constexpr is present in the declaration
of u0,u1,â¦,uNâ1 if and only ifconstexpr is one of the [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s* of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]")[.](#5.3.sentence-2)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L931)

[*Example [1](#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](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L947)

[*Example [2](#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](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L962)

[*Example [3](#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*]
