Search code examples
c++gccclanglanguage-lawyerclang++

Why are the compiler errors inconsistent in gcc and clang when casting an xvalue to a non-const lvalue reference?


Can someone explain why both compilers throw an error on the second example whereas only gcc throws an error on the first example? Is it somehow related to the result of the static_cast being an xvalue?

int& example1 = reinterpret_cast<int&>(static_cast<int&&>(10));
//(gcc 10.2) error: invalid cast of an rvalue expression of type 'int' to type 'int&'
//(clang 11.0.0) no errors

int& example2 = reinterpret_cast<int&>(10);
//(gcc 10.2) error: invalid cast of an rvalue expression of type 'int' to type 'int&'
//(clang 11.0.0) error: reinterpret_cast from rvalue to reference type 'int &'

Also I'm not sure but I think the first example is well-formed because according to the standard, an xvalue is a type of a glvalue, right? And this [expr.reinterpret.cast]/11 part of the standard says that I should be able to cast T1 glvalues to the type “reference to T2” with the T1 being the same type as T2 in this case.


Solution

  • reinterpret_cast<int&>(10);
    

    This program is ill-formed, as the expression being converted from is a prvalue. From [expr.reinterpret.cast]/1:

    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 or an rvalue reference to function type, the result is an lvalue; [...] Conversions that can be performed explicitly using reinterpret_­cast are listed below. No other conversion can be performed explicitly using reinterpret_­cast.

    None of the clauses that follows allows a reinterpret_cast from a (p)rvalue that is not a pointer.


    #include <memory>
    reinterpret_cast<int&>(std::move(10));
    

    Here, the expression being converted from is an xvalue, and as shown in the Q&A linked to in a comment by @LanguageLawyer (which is arguably a dupe target for this Q&A)

    this is well-formed, as of C++14 (updated as a DR fix also to C++11) and the actual implementation of CWG 1268:

    1268. reinterpret_cast of an xvalue operand Section: 8.2.10 [expr.reinterpret.cast]

    Status: CD3

    Submitter: Michael Wong

    Date: 2011-03-21

    [Moved to DR at the October, 2012 meeting.]

    8.2.10 [expr.reinterpret.cast] paragraph 11, dealing with casting to reference types, only allows an lvalue operand. Presumably it should allow a glvalue operand when the target is an rvalue reference type.

    [...]

    Note that the emphasized segment proposes to allow this only when the target is an rvalue reference, but the actually updated [expr.reinterpret.cast]/11 removed this restriction.

    Consequently, GCC is wrong to reject the first example.