Why is static_cast<Object&&> necessary in this function?

Advertisements

Trying to understand std::move, I found this answer to another question.

Say I have this function

Object&& move(Object&& arg)
{
    return static_cast<Object&&>(arg);
}

What I think I understand:

  • arg is an lvalue (value category).
  • arg is of type "rvalue ref to Object".
  • static_cast converts types.
  • arg and the return type both being of type "rvalue ref to Object", the static_cast is unnecessary.

However, the linked answer says:

Now, you might wonder: do we even need the cast? The answer is: yes, we do. The reason is simple; named rvalue reference is treated as lvalue (and implicit conversion from lvalue to rvalue reference is forbidden by standard).

I still don’t understand why the static_cast is necessary given what I said above.

>Solution :

the static_cast is unnecessary.

It may seem so, but it is necessary. You can find out easily by attempting to write such function without the cast, as the compiler should tell you that the program is ill-formed. The function (template) returns an rvalue reference. That rvalue reference cannot be bound to an lvalue. The id-expression arg is an lvalue (as you stated) and hence the returned rvalue reference cannot be bound to it.

It might be easier to understand outside of return value context. The rules are same here:

T obj;
T&& rref0 = obj;                     // lvalue; not OK
T&& rref1 = static_cast<T&&>(obj);   // xvalue; OK
T&& rref2 = rref1;                   // lvalue; not OK
T&& rref3 = static_cast<T&&>(rref1); // xvalue; OK

Leave a ReplyCancel reply