Целью identity
было сделать T
не подлежащим вычету.То есть заставить клиента явно указывать T
при вызове forward
.
forward(a); // compile-time error
forward<A>(a); // ok
. Причина, по которой это необходимо, заключается в том, что параметром шаблона является переключатель , с которымклиент говорит компилятору пересылать аргумент как lvalue или как rvalue.Если вы случайно забыли предоставить эту информацию, то lvalues всегда возвращаются как lvalues, а rvalues всегда возвращаются как rvalue.Хотя поначалу это может звучать так, как вы хотите, на самом деле это не так.
template <class T, class A1>
std::shared_ptr<T>
factory(A1&& a1)
{
return std::shared_ptr<T>(new T(std::forward<A1>(a1)));
}
В приведенном выше примере a1
всегда является lvalue.Но «переключатель» A1
может быть или не быть ссылкой на lvalue.Если это ссылка lvalue, a1
возвращается как lvalue, в противном случае a1
возвращается как rvalue.Если автор фабрики случайно забывает предоставить A1, использование identity
напоминает ему во время компиляции.
Примечание: в окончательном варианте отсутствует identity
, но используется remove_reference
в том же месте длята же цель.