This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Adopted at the June, 2016 meeting.]
Consider the following example:
struct A { void *p; constexpr A(): p(this) {} }; constexpr A a; // well-formed constexpr A b = A(); // ?
The declaration of a seems well-formed because the address of a is constant.
The declaration of b, however, seems to depend on whether copy elision is performed. If it is, the declaration is the equivalent of a; if not, however, this creates a temporary and initializes p to the address of that temporary, making the initialization non-constant and the declaration ill-formed.
It does not seem desirable for the well-formedness of the program to depend on whether the implementation performs an optional copy elision.
Notes from the November, 2014 meeting:
CWG decided to leave it unspecified whether copy elision is performed in cases like this and to add a note to 11.4.5.3 [class.copy.ctor] to make clear that that outcome is intentional.
Notes from the May, 2015 meeting:
CWG agreed that copy elision should be mandatory in constant expressions.
Proposed resolution (April, 2016):
Change 7.7 [expr.const] paragraph 1 as follows:
...Expressions that satisfy these requirements, assuming that copy elision is performed, are called constant expressions. [Note:...
Change 9.2.6 [dcl.constexpr] paragraph 7 as follows, breaking the existing running text into a bulleted list:
A call to a constexpr function produces the same result as a call to an equivalent non-constexpr function in all respects except that
a call to a constexpr function can appear in a constant expression (7.7 [expr.const]) and
copy elision is mandatory in a constant expression (11.4.5.3 [class.copy.ctor]).
Change 11.4.5.3 [class.copy.ctor] paragraph 31 as follows:
...This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):
...
Copy elision is required where an expression is evaluated in a context requiring a constant expression (7.7 [expr.const]) and in constant initialization (6.9.3.2 [basic.start.static]). [Note: Copy elision might not be performed if the same expression is evaluated in another context. —end note] [Example:
class Thing { public: Thing(); ~Thing(); Thing(const Thing&); }; Thing f() { Thing t; return t; } Thing t2 = f(); struct A { void *p; constexpr A(): p(this) {} }; constexpr A a; // well-formed, a.p points to a constexpr A b = A(); // well-formed, b.p points to b void g() { A c = A(); // well-formed, c.p may point to c or to an ephemeral temporary }Here the criteria for elision can be combined...