According to http://en.cppreference.com/w/cpp/utility/move
std::move
is declared as follows:
template <typename T>
std::remove_reference<T>::type&& move(T&& t);
As far as my understanding goes, when code is templated, the deduction of T
in typename T
looses information about reference, so following:
template <typename T>
void someFunction(T&& value);
when used like:
int five=5;
someFunction(five);
then
value
is of type int&
T
is int
or
const float value = 5.25;
someFunction(value);
then
value
is of type const float&
T
is const float
.If this is so, then there is no point in move declaration to declare returned type as:
std::remove_reference<T>::type&&
, because T is already not a reference.
Moreover, if std::move
takes as argument a reference (l-value reference in practice), then returning static_cast<T&&>(t)
in std::move
in fact due to reference collapsing will return l-value reference or r-value reference, so it will behave more like std::forward
not move. So what is a trick, that makes it work properly, that I do not understand?
Your examples are incorrect:
int five=5;
someFunction(five);
In this case, T
is deduced as int&
, not int
. The same goes for the second example; T
is deduced as const int&
.
As such, returning just T&&
would mean T&& &
, which is T&
due to reference collapsing rules.
This is why the std::remove_reference
is required, to ensure that there are no references on the type to prevent reference collapsing from taking place.