Search code examples
c++c++11c++14move

why std::move uses std::remove_reference?


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?


Solution

  • 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.