CWG Issue 3044 (original) (raw)
This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118f. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-11-07
3044. Iterating expansion statements woes
Section: 8.7 [stmt.expand]Status: readySubmitter: Jakub JelinekDate: 2025-07-08
(From submissions#725 and#730.)
The rewrite of iterating expansion statements contains:
static constexpr auto iter = begin + i;
where the type of i is unspecified, but overload resolution of + depends on the type of i.
Furthermore, the rewrite contains
for (auto i = begin ; i != end ; ++i, ++result);
which might invoke an overloaded comma operator, which is undesirable.
Furthermore, because of the use of static in the rewrite, the example in 8.7 [stmt.expand] paragraph 7 is ill-formed.
Possible resolution (July 2025) [SUPERSEDED]:
- Change in 8.7 [stmt.expand] bullet 5.2 as follows:
Otherwise, if S is an iterating expansion statement, S is equivalent to:
{
init-statement
staticconstexpr auto&& range = expansion-initializer ;
staticconstexpr auto begin = begin-expr; // see 8.6.5 [stmt.ranged]
staticconstexpr auto end = end-expr; // see 8.6.5 [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) ++result;
return result; // distance from begin to end
}()and Si is
{
staticconstexpr auto iter = begin +ii;
for-range-declaration = *iter ;
compound-statement
}The variables range , begin , end , and iter are defined for exposition only. The identifier i is considered to be a prvalue of type decltype(begin - begin); the program is ill-formed if i is not representable as such a value. [Note 1 : The instantiation is ill-formed if _range_is not a constant expression (7.7 [expr.const]). -- end note]
- No change in 8.7 [stmt.expand] paragraph 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_]
Proposed resolution (approved by CWG 2025-11-06):
Change in 8.7 [stmt.expand] bullet 5.2 as follows:
Otherwise, if S is an iterating expansion statement, S is equivalent to:
{ init-statement
staticconstexpr auto&& range = expansion-initializer ;staticconstexpr auto begin = begin-expr; // see 8.6.5 [stmt.ranged]staticconstexpr auto end = end-expr; // see 8.6.5 [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) ++result; return result; // distance from begin to end }()and Si is
{
staticconstexpr auto iter = begin +idecltype(begin - begin){i}; for-range-declaration = *iter ; compound-statement }The variables range , begin , end , and iter are defined for exposition only. The identifier i is considered to be a prvalue of type std::ptrdiff_t; the program is ill-formed if i is not representable as such a value. [Note 1 : The instantiation is ill-formed if _range_is not a constant expression (7.7 [expr.const]). -- end note]