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

2024-05-06


2549. Implicitly moving the operand of a throw-expression in unevaluated contexts

Section: 7.5.4.3  [expr.prim.id.qual]     Status: review     Submitter: Richard Smith     Date: 2022-03-11

Consider:

  void f() {
    X x;
    // Is x an lvalue or an xvalue here?
    void g(int n = (decltype((throw x, 0))()));  // status quo: x is move-eligible here
  }

  void f() {
    X x;
    struct A {
      void g() {
        try {
          struct Y {
            // Is x an lvalue or an xvalue here?
            void h(int n = (decltype((throw x, 0))()));
          };
        } catch (...) { }
      }
    };
  }

11.9.6 [class.copy.elision] paragraph 3 specifies:

An implicitly movable entity is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. In the following copy-initialization contexts, a move operation is first considered before attempting a copy operation:

Thus, in the first example above, x is treated as an xvalue, but it is treated as an lvalue in the second example. This outcome is surprising.

(P2266R2 (Simpler implicit move) moved this wording, introduced by P1825R0 (Merged wording for P0527R1 and P1155R3), from 11.9.6 [class.copy.elision] to 7.5.4.2 [expr.prim.id.unqual].)

Proposed resolution:

Change in 7.5.4.2 [expr.prim.id.unqual] paragraph 4:

An implicitly movable entity is a variable of with automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. In the following contexts, an An id-expression is move-eligible: if