As stated at cplusplus.com, std::forward
has two signatures:
template <class T> T&& forward (typename remove_reference<T>::type& arg) noexcept;
template <class T> T&& forward (typename remove_reference<T>::type&& arg) noexcept;
The typical use of std::forward
is to preserve rvalueness while passing arguments to other functions. Let's illustrate this with an example:
void overloaded(int &) { std::cout << "lvalue"; }
void overloaded(int &&) { std::cout << "rvalue"; }
template <typename T>
void fwd(T && t)
{
overloaded(std::forward<T>(t));
}
When we call fwd(0)
, T
deduces to int
(t
has type int &&
). Then we call std::forward<int>(t)
. The result of that call is expression of type int &&
so the second version of overloaded
function is selected and the program prints "rvalue" to the standard output.
When we call fwd(i)
(where i is some int variable), T
deduces to int&
(t
has type int &
). Then we call std::forward<int&>(t)
. The result of that call (after applying reference collapsing rules) is expression of type int &
so the first version of overloaded
function is selected and the program prints "lvalue" to the standard output.
In both these cases we use the first overload of std::forward
(the one taking typename remove_reference<T>::type& arg
). It is because even if the type of t
is int &&
it binds to lvalue reference (because named variable of type "rvalue reference to something" is itself lvalue and lvalues can't bind to rvalue reference).
Question 1:
What is that second overload of std::forward
for? Can you think of some practical example, that uses the overload taking arg
by rvalue reference?
Question 2:
cplusplus.com says:
Both signatures return the same as:
static_cast<decltype(arg)&&>(arg)
The problem I have with that, is that I'm pretty sure that it is wrong. When we try to return this from the first overload of std::forward
we get a compilation error.
When fwd
is called with int
rvalue, it calls the first overload of std::forward
with T = int
. Then, decltype(arg)
will become int&
so static_cast<decltype(arg)&&>(arg)
will collapse to static_cast<int&>(arg)
. But the return type is int &&
and we get compilation error:
cannot bind ‘std::remove_reference<int>::type {aka int}’ lvalue to ‘int&&’
Both overloaded versions of std::forward
should return static_cast<T&&>(arg)
. Am I right?
Do you think that the quote from cplusplus.com is a mistake?