Por que std :: move usa uma referência direta?

A implementação destd::move basicamente se parece com isso:

template<typename T>
typename std::remove_reference<T>::type&&
move(T&& t)
{
    return static_cast<typename std::remove_reference<T>::type&&>(t);
}

Observe que o parâmetro destd::move é uma referência universal (também conhecida como referência de encaminhamento, mas não estamos encaminhando aqui). Ou seja, você podestd::move lvalues e rvalues:

std::string a, b, c;
// ...
foo(std::move(a));       // fine, a is an lvalue
foo(std::move(b + c));   // nonsense, b + c is already an rvalue

Mas desde que todo o ponto destd::move é converter em um valor, por que temos permissão parastd::move rvalues? Não faria mais sentido sestd::move aceitaria apenas lvalues?

template<typename T>
T&&
move(T& t)
{
    return static_cast<T&&>(t);
}

Então a expressão sem sentidostd::move(b + c) causaria um erro em tempo de compilação.

A implementação acima destd::move também seria muito mais fácil de entender para iniciantes, porque o código faz exatamente o que parece: pega um lvalue e retorna um rvalue. Você não precisa entender referências universais, colapso de referência e meta-funções.

Então porque foistd::move projetado para levar lvalues e rvalues?

questionAnswers(2)

yourAnswerToTheQuestion