Search code examples
c++movervaluelvalue

Why was it nessesury to allow std::move accept reference to lvalue besides reference to rvalue in Uref embodiment for both?


Considering that rvalue-ness and lvalue-ness are not a features of objects but of expressions.

Why isn't std::move implemented only for lvalue reference argument, but for universal one? Whereas it is useful only for retrieving rvalue reference from an lvalue? When rvalue is rvalue already and it does not need std::move functionality.

template <typename T>
typename std::remove_reference_t<T>&& move(T&& x)
{
  return static_cast<std::remove_reference_t<T>&&>(x);
}

Solution

  • Why isn't std::move implemented only for lvalue reference argument, but for universal one?

    Because lvalue references to non-const cannot be bound to xvalues.

    When rvalue is rvalue already and it does not need std::move functionality.

    We want std::move(some_expression) to work whether some_expression is an rvalue expression or lvalue expression. That is particularly important in templates where that detail can depend on template arguments and we don't want to write separate specialisations for each.

    Basically same reason as why these are allowed:

    using T = const U;
    const T var;
    
    using S = T&;
    S& ref = var;
    

    In this case, we want to be able to declare const T var, and S& whether the types are already const/reference or not.