This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-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:
- ...
- if the operand of a throw-expression (7.6.18 [expr.throw]) is a (possibly parenthesized) id-expression that names an implicitly movable entity that belongs to a scope that does not contain the compound-statement of the innermost try-block or function-try-block (if any) whose compound-statement or ctor-initializer contains the throw-expression,
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.5.2 [expr.prim.id.unqual].)
Proposed resolution:
Change in 7.5.5.2 [expr.prim.id.unqual] paragraph 4:
An implicitly movable entity is a variableofwith automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type.In the following contexts, anAn id-expression is move-eligible:if
- it names an implicitly movable entity declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression and
Iftheid-expression(possibly parenthesized) id-expression is the operand of
- a return or co_return statement
, and names an implicitly movable entity declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expressionorif the id-expression (possibly parenthesized) is the operand ofa potentially-evaluated throw-expression, and names an implicitly movable entity that belongs to a scope that does not contain the compound-statement of the innermost lambda-expression, try-block, or function-try-block (if any) whose compound-statement or ctor-initializer encloses the throw-expressionwhere no try-block or function-try-block intervenes between the declaration of the entity and the innermost enclosing scope of the throw-expression.