20

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; }
CharlesB
  • 86,532
  • 28
  • 194
  • 218
user2023370
  • 10,488
  • 6
  • 50
  • 83

1 Answers1

18

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.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • I think this is better explained than my answer, so I've deleted mine. I'm still wondering whether there is a good example where you pass an rvalue argument to `forward`. Is there any usecase? Perhaps in the Standard library? – Johannes Schaub - litb Apr 01 '11 at 13:07
  • See use case B in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2951.html . Note that this paper proposes a forward implementation which ultimately was found to be problematic. However the final forward specification passes and correctly fails all use cases presented in this paper. Here is the paper http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html that points out the final use case that N2951 missed. – Howard Hinnant Apr 01 '11 at 13:17