Due to the shortcomings of lvalue and rvalue references in C++, forwarding references (or some would call it universal references) becomes the alternative for resources’ referencing or copying.
It is rather easy to confuse the syntax of rvalue references and forwarding references. Just remember that forwarding references is always come with template, and it is immediately attached to the type itself. See the following examples:
void f(Widget&& w); // rvalue reference
template<typename T>
void f(Widget<T>&& w); // still a rvalue reference
template<typename T>
void f(T&& w); // forwarding reference
Forwarding references could be used alongside with variadic template in order to accept multiple arguments with no hassle of value type conversion. This is showed as the following:
template<typename... T>
void f(T&&... w) {
do_something(std::forward<T>(w)...);
}
Although forwarding references is a good alternative for generality, it does not actually preserve the value type of the arguments after they enter the local scope. In order to do this, we need 202203291851#.
Caution
Because of the generality of forwarding reference, there is always a possibility that some functions does not do what you think. Remember this rule: C++ compiler will always find the perfect match for a generated function with the given parameters, otherwise a function with forwarding reference will almost always be chosen as the alternative.
Do not forward something twice! Once we have forwarded an object, it is not yours to use anymore.