Can reinterpret_cast (or any cast) convert xvalues to lvalues?

前端 未结 3 1455
醉酒成梦
醉酒成梦 2020-12-16 23:02

Is the following code legal (by C++11 and/or C++14 standard(s))?

#include 
#include 

using namespace std;

void foo(int &         


        
3条回答
  •  我在风中等你
    2020-12-16 23:42

    Update: The code is ill-formed in C++11. Answer below is for C++14. See note at the end of this answer.

    I believe this code is both well-formed and well-defined. Here's why.

    The result of std::move is an xvalue [1], which is a type of glvalue; and converting a glvalue to an lvalue reference with reinterpret_cast appears to be allowed by the wording of the standard:

    A glvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast. The result refers to the same object as the source glvalue, but with the specified type. [ Note: That is, for lvalues, a reference cast reinterpret_cast(x) has the same effect as the conversion *reinterpret_cast(&x) with the built-in & and * operators (and similarly for reinterpret_cast(x)). — end note ] No temporary is created, no copy is made, and constructors (12.1) or conversion functions (12.3) are not called.73

    Since "pointer to int" can be converted to "pointer to int", this reinterpret_cast is also allowed. The standard doesn't say anything about whether the destination type has to be an lvalue reference or rvalue reference.

    The result of the cast is well-defined by the paragraph above: it refers to the same object as the source glvalue---that is, a temporary int object with the value 5. ([dcl.init.ref] specifies that a temporary is created when a prvalue is bound to a reference.)

    Accessing the value through the int& also doesn't violate any aliasing rules since the original object was also of type int. In fact I believe it would even be well-defined to modify the temporary through the lvalue thus obtained.

    Note: The C++11 wording says "lvalue expression", not "glvalue expression". The wording with "glvalue expression" is from N3936, which is the final working draft for C++14. I'm not an expert in how the standardization process works, but I believe this means that the change of "lvalue" to "glvalue" was already voted in by the committee, and when ISO publishes the C++14 standard, it's going to be pretty similar to what it says above.

    [1] Except in the rare case in which the argument is a function; in that case the result is an lvalue, since there are no function rvalues.

提交回复
热议问题