Copy elision in constant expressions
7.7 [expr.const]
Jason Merrill

Created on 2014-10-16.00:00:00 last changed 49 months ago


Date: 2016-04-15.00:00:00

Proposed resolution (April, 2016):

  1. Change 7.7 [expr.const] paragraph 1 as follows:

  2. ...Expressions that satisfy these requirements, assuming that copy elision is performed, are called constant expressions. [Note:...
  3. Change 9.2.6 [dcl.constexpr] paragraph 7 as follows, breaking the existing running text into a bulleted list:

  4. 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 (_N4750_.15.8 [class.copy]).

  5. Change _N4750_.15.8 [class.copy] paragraph 31 as follows:

  6. ...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 ( [basic.start.static]). [Note: Copy elision might not be performed if the same expression is evaluated in another context. —end note] [Example:

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

Date: 2015-05-15.00:00:00

Notes from the May, 2015 meeting:

CWG agreed that copy elision should be mandatory in constant expressions.

Date: 2014-11-15.00:00:00

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 _N4750_.15.8 [class.copy] to make clear that that outcome is intentional.

Date: 2016-06-15.00:00:00

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

Date User Action Args
2017-02-06 00:00:00adminsetmessages: + msg6100
2017-02-06 00:00:00adminsetmessages: + msg6099
2017-02-06 00:00:00adminsetstatus: drafting -> cd4
2014-11-24 00:00:00adminsetmessages: + msg5199
2014-10-16 00:00:00admincreate