This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-19
Consider:
struct Foo {};
struct Bar {
mutable Foo f;
};
constexpr Bar b{}; // #1
In C++20, Foo and Bar are literal types, and #1 is well-formed. In C++23, the requirement for the variable b changed to "constant destruction". However, Bar does not have constant destruction, because its mutable member violates 7.7 [expr.const] bullet 5.17:
- ...
- an invocation of a destructor (11.4.7 [class.dtor]) or a function call whose postfix-expression names a pseudo-destructor (7.6.1.3 [expr.call]), in either case for an object whose lifetime did not begin within the evaluation of E;
- ...
This is because the mutable member is considered to have its lifetime begin outside of E per 7.7 [expr.const] paragraph 9:
An object a is said to have constant destruction if:
- it is not of class type nor (possibly multidimensional) array thereof, or
- it is of class type or (possibly multidimensional) array thereof, that class type has a constexpr destructor, and for a hypothetical expression E whose only effect is to destroy a, E would be a core constant expression if the lifetime of a and its non-mutable subobjects (but not its mutable subobjects) were considered to start within E.
Proposed resolution (reviewed by CWG 2024-03-01):
Change in 7.7 [expr.const] paragraph 10 as follows:
An object a is said to have constant destruction if:
- it is not of class type nor (possibly multidimensional) array thereof, or
- it is of class type or (possibly multidimensional) array thereof, that class type has a constexpr destructor, and for a hypothetical expression E whose only effect is to destroy a, E would be a core constant expression if any invocation of a trivial destructor for a mutable subobject is ignored and if the lifetime of a and its non-mutable subobjects (but not its mutable subobjects) were considered to start within E.