In A Brief Introduction to Rvalue References, forward
is defined as follows:
template <typename T>
struct identity { typedef T type; };
template <typename T>
T &&forward(typename identity<T>::type &&a) { return a; }
What purpose does the identity
class perform? Why not:
template <typename T>
T &&forward(T &&a) { return a; }
The purpose of identity
was to make T
non-deducible. That is, to force the client to explicitly supply T
when calling forward
.
forward(a); // compile-time error
forward<A>(a); // ok
The reason this is necessary is because the template parameter is the switch with which the client tells the compiler to forward the argument as either an lvalue or as an rvalue. If you accidentally forget to supply this information then lvalues are always returned as lvalues and rvalues are always returned as rvalues. While at first that may sound like what you want, it really isn't.
template <class T, class A1>
std::shared_ptr<T>
factory(A1&& a1)
{
return std::shared_ptr<T>(new T(std::forward<A1>(a1)));
}
In the above example a1
is always an lvalue. But the "switch" A1
may or may not be an lvalue reference. If it is an lvalue reference, a1
gets returned as an lvalue, otherwise a1
gets returned as an rvalue. If the author of factory accidentally forgets to supply A1, the use of identity
reminds him at compile time.
Note: The final draft lacks identity
, but uses remove_reference
in the same place for the same purpose.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With