This is really intended behavior. Template form functions:
template< class T > Ret Function( T&& param ) { ... }
follows special rules (Ret may or may not be a pattern, it does not matter). T&& is called a universal reference, and it can basically be attached to everything. This is because when the template calculation is triggered and the parameter is in this form (beware, vector<T>&& not a universal reference, and is not C<T> for any other template parameter), the drop rule is applied links:
T = int & => T && = int && & and which collapse to one int &
full correlation table:
& + && = & && + & = & && + && = &&
So, when you have the above function
int a = 5; int b& = a; Function( a );
In case 1, T = int & and the type being deduced is int & (since a is an lvalue), so the function has the following signature:
Ret Function( int& param ) // int& && collapses to int&
In case 2, T = int &
Ret Function( int& param ) // int& && collapses to int&
In case 3, T = int
Ret Function( int&& param )
This rule of collapse is what the committee deemed reasonable to do the perfect forwarding work. You can find the long story in this Scott Meyer video
source share