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

2023-01-15


690. The dynamic type of an rvalue reference

Section: Clause 3  [intro.defs]     Status: CD2     Submitter: Eelis van der Weegen     Date: 7 April, 2008

N2800 comment FR 5

[Voted into WP at March, 2010 meeting as document N3055.]

According to Clause 3 [intro.defs], “dynamic type,”

The dynamic type of an rvalue expression is its static type.

This is not true of an rvalue reference, which can be bound to an object of a class type derived from the reference's static type.

Proposed resolution (June, 2008):

Change Clause 3 [intro.defs], “dynamic type,” as follows:

the type of the most derived object (6.7.2 [intro.object]) to which the lvalue denoted by an lvalue or an rvalue-reference (Clause 7 [expr]) expression refers. [Example: if a pointer (9.3.4.2 [dcl.ptr]) p whose static type is “pointer to class B” is pointing to an object of class D, derived from B (11.7 [class.derived]), the dynamic type of the expression *p is “D.” References (9.3.4.3 [dcl.ref]) are treated similarly. —end example] The dynamic type of an rvalue expression that is not an rvalue reference is its static type.

Notes from the June, 2008 meeting:

Because expressions have an rvalue reference type only fleetingly, immediately becoming either lvalues or rvalues and no longer references, the CWG expressed a desire for a different approach that would somehow describe an rvalue that resulted from an rvalue reference instead of using the concept of an expression that is an rvalue reference, as above. This approach could also be used in the resolution of issue 664.

Additional note (August, 2008):

This issue, along with issue 664, indicates that rvalue references have more in common with lvalues than with other rvalues: they denote particular objects, thus allowing object identity and polymorphic behavior. That suggests that these issues may be just the tip of the iceberg: restrictions on out-of-lifetime access to objects, the aliasing rules, and many other specifications are written to apply only to lvalues, on the assumption that only lvalues refer to specific objects. That assumption is no longer valid with rvalue references.

This suggests that it might be better to classify all rvalue references, not just named rvalue references, as lvalues instead of rvalues, and then just change the reference binding, overload resolution, and template argument deduction rules to cater to the specific kind of lvalues that are associated with rvalue references.

Additional note, May, 2009:

Another place in the Standard where the assumption is made that only lvalues can have dynamic types that differ from their static types is 7.6.1.8 [expr.typeid] paragraph 2.

(See also issues 846 and 863.)

Additional note, September, 2009:

Yet another complication is the statement in 7.2.1 [basic.lval] paragraph 9 stating that “non-class rvalues always have cv-unqualified types.” If an rvalue reference is an rvalue, then the following example is well-formed:

    void f(int&&);    // reference to non-const
    void g() {
        const int i = 0;
        f(static_cast<const int&&>(i));
    }

The static_cast binds an rvalue reference to the const object i, but the fact that it's an rvalue means that the cv-qualification is lost, effectively allowing the parameter of f, a reference to non-const, to bind directly to the const object.

Proposed resolution (February, 2010):

See paper N3030.