CWG Issue 2022 (original) (raw)

This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-11-05


2022. Copy elision in constant expressions

Section: 7.7 [expr.const]Status: CD4Submitter: Jason MerrillDate: 2014-10-16

[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 initializesp 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):

  1. 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:...

  1. 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

  1. 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.10.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...