As the page you linked poses it:
This is a helper function to allow perfect forwarding of arguments
taken as rvalue references to deduced types, preserving any potential
move semantics involved.
When you have a named value, as in
void f1(int& namedValue){
...
}
or in
void f2(int&& namedValue){
...
}
it evaluates, no matter what, to an lvalue
.
One more step. Suppose you have a template function
template <typename T>
void f(T&& namedValue){
...
}
such function can either be called with an lvalue or with an rvalue; however, no matter what, namedValue evaluates to an lvalue
.
Now suppose you have two overloads of an helper function
void helper(int& i){
...
}
void helper(int&& i){
...
}
calling helper
from inside f
template <typename T>
void f(T&& namedValue){
helper(namedValue);
}
will invariably call the first overload for helper
, since namedValue
is, well, a named value which, naturally, evaluates to an lvalue
.
In order to get the second version called when appropriate (i.e. when f
has been invoked with a rvalue parameter), you write
template <typename T>
void f(T&& namedValue){
helper( std::forward<T>(namedValue) );
}
All of this is expressed much concisely in the documentation by the following
The need for this function stems from the fact that all named values
(such as function parameters) always evaluate as lvalues (even those
declared as rvalue references), and this poses difficulties in
preserving potential move semantics on template functions that forward
arguments to other functions.