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);
}
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.