Looking at Scott Meyer's Effective Modern C++ pages 200-201, the suggested simplified implementation of std::forward
could be (did see the proper implementation elsewhere):
template <typename T>
T&& forward(std::remove_reference_t<T>& param)
{ return static_cast<T&&>(param); }
And when accepting an rvalue Widget, it becomes:
Widget&& forward(Widget& param)
{ return static_cast<Widget&&>(param); }
Now, if you take that substituted code, and do:
struct Widget { };
Widget&& forward(Widget& param)
{ return static_cast<Widget&&>(param); }
template <typename T>
void G(T&& uref)
{ }
template <typename T>
void F(T&& uref)
{ G(forward(uref)); }
int main()
{
Widget x;
F(std::move(x));
}
What I can't wrap my head around, and didn't see a direct answer on SO yet, is: in forward
how does parameter Widget& param
manage to accept Widget&&
from F()? Normally gcc-5.0 would complain like so with non-template code:
error: invalid initialization of non-const reference of type ‘Widget&’ from an rvalue of type ‘std::remove_reference::type {aka Widget}’
(Question #27501400 nearly touches the topic, but not quite. It shows the standard as having both lvalue & and rvalue && versions.)