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?