std::forward
has a single use case: to cast a templated function parameter (inside the function)
to the value category (lvalue or rvalue) the caller used to pass it.
std::move
takes an object and allows you to treat it as a temporary (an rvalue). Although it isn’t a
semantic requirement, typically a function accepting a reference to an rvalue will invalidate it.
When you see std::move, it indicates that the value of the object should not be used afterwards,
but you can still assign a new value and continue using it.
Let's say you have the following:
struct S { };
void f(S& s)
{
std::cout<<"S&" <<std::endl;
}
void f(S&& s)
{
std::cout<<"S&&" <<std::endl;
}
template< typename T>
void wrap(T t)
{
f(t);
}
In your main, this will call lvalue function of f()
S s;
f(s);
This will call rvalue function of f()
f(S());
now if we have wrapper class for f()
and we call the following we get lvalue which is wrong
wrap(S());
so we have to change the warp function to the following to forward to the correct value category:
template< typename T>
void wrap_forward(T t)
{
f(std::forward<T>(t));
}
if we use forward we will get the rvalue f()
which is the correct one:
wrap_forward(S());