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?