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

2024-04-18


842. Casting to rvalue reference type

Section: 7.6.1.10  [expr.reinterpret.cast]     Status: CD2     Submitter: Steve Adamczyk     Date: 20 March, 2009

[Voted into WP at October, 2009 meeting.]

Both const_cast (7.6.1.11 [expr.const.cast] paragraph 1) and reinterpret_cast (7.6.1.10 [expr.reinterpret.cast] paragraph 1) say,

If T is an lvalue reference type, the result is an lvalue; otherwise, the result is an rvalue and the lvalue-to-rvalue (7.3.2 [conv.lval]), array-to-pointer (7.3.3 [conv.array]), and function-to-pointer (7.3.4 [conv.func]) standard conversions are performed on the expression v.

This introduces a contradiction in the text. According to 7.6.1.11 [expr.const.cast] paragraph 4,

The result of a reference const_cast refers to the original object.

However, the lvalue-to-rvalue conversion applied to the operand when the target is an rvalue reference type creates a temporary if the operand has class type (7.3.2 [conv.lval] paragraph 2), meaning that the result will not refer to the original object but to the temporary.

A similar problem exists for reinterpret_cast: according to 7.6.1.10 [expr.reinterpret.cast] paragraph 11,

a reference cast reinterpret_cast<T&>(x) has the same effect as the conversion *reinterpret_cast<T*>(&x) with the built-in & and * operators (and similarly for reinterpret_cast<T&&>(x)). The result refers to the same object as the source lvalue, but with a different type.

Here the issue is that the unary & operator used in the description requires an lvalue, but the lvalue-to-rvalue conversion is applied to the operand when the target is an rvalue reference type.

It would seem that the lvalue-to-rvalue conversion should not be applied when the target of the cast is an rvalue reference type.

Proposed resolution (July, 2009):

  1. Change 7.6.1.10 [expr.reinterpret.cast] paragraph 1 as follows:

  2. The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T. If T is an lvalue reference type, the result is an lvalue; if T is an rvalue reference type, the result is an rvalue; otherwise, the result is an rvalue and the lvalue-to-rvalue (7.3.2 [conv.lval]), array-to-pointer (7.3.3 [conv.array]), and function-to-pointer (7.3.4 [conv.func]) standard conversions are performed on the the expression v. Conversions that can be performed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.
  3. Change 7.6.1.11 [expr.const.cast] paragraph 1 as follows:

  4. The result of the expression const_cast<T>(v) is of type T. If T is an lvalue reference type, the result is an lvalue; if T is an rvalue reference type, the result is an rvalue; otherwise, the result is an rvalue and the lvalue-to-rvalue (7.3.2 [conv.lval]), array-to-pointer (7.3.3 [conv.array]), and function-to-pointer (7.3.4 [conv.func]) standard conversions are performed on the expression v. Conversions that can be performed explicitly using const_cast are listed below. No other conversion shall be performed explicitly using const_cast.