Here is an example, perhaps archetypal, for which we need remove_reference , in the implementation of std::move : The goal is to return the link type rvalue based on the inferred type of the function argument.
Example: Foo x; move(x); Foo x; move(x); Here move(x) should return the type Foo&& . But the move argument is an expression of type Foo& . So how does the move function infer the correct type?
The first attempt is to use the normal output of the template argument and use listing:
template <typename T> T && move(??? x) { return static_cast<T&&>(x); }
But what should go to ??? ? If we say T x , then T will be printed as Foo& ; if we say T & x , then T = Foo , and if we say T && x , this will not match at all. The second version, T & x , seems useful.
But then the function does not work for r values ββto start with (for example, move(Foo(...)) . In this case, we want T && x so that T = Foo and T&& = Foo&& if desired. We could have two overloads , but with multiple overloads it is undesirable because it requires complexity once again.And finally, if someone must explicitly specify the template parameter as move<Foo&>(x) , the function will never work, because when T = Foo& , then T&& = Foo& .
So comes remove_reference :
template <typename T> typename std::remove_reference<T>::type && move(T && x) { return static_cast<typename std::remove_reference<T>::type &&>(x); }
First, the new link folding rules imply that T is output as Foo& or Foo&& in two cases. Then remove_reference splits the link and gives the type Foo anyway, and adding && makes the desired return type Foo&& .
In a simplified summary: we need to remove_reference because (Foo&)&& is Foo& , not Foo&& . If you ever write template code that needs a basic type of template parameter that can be displayed as U& or U&& , you can use this model.