When you use T&& , this is not an rvalue reference, it is a universal reference parameter. They are declared the same, but they behave differently.
When you delete template parameters, you are no longer in the output context and actually refer to rvalue: they are bound only to rvalues, of course.
In the output context (that is, when type deduction occurs), T&& can be either an rvalue reference or an lvalue reference. Universal links can be associated with almost all combinations ( const , const volatile , etc.), and in your case: const T& .
Now your train of thought should be efficient and overload for rvalues ββand then lvalues, but what happens is that universal reference overloading is the best match when outputting template arguments. Therefore, it will be selected on top of the overload const T& .
Usually you want to save a universal reference function and map it to std::forward<T>() in order to refine the argument (s). This eliminates the need for your const T& overload, since a universal reference version will be used.
Please note that just because you see && in the displayed context does not mean that it is a universal link; && should be added to the type being deduced, so here is an example of what the rvalue reference is actually:
template<class T> void f_(std::vector<T>&& arg)
Here's a great talk about this: https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11
source share