Ответ 1
Цель identity
заключалась в том, чтобы сделать T
невыводимым. То есть, чтобы заставить клиента явно отправлять T
при вызове forward
.
forward(a); // compile-time error
forward<A>(a); // ok
Причина, по которой это необходимо, заключается в том, что параметр шаблона является коммутатором, с которым клиент сообщает компилятору передать аргумент как значение lvalue, либо как rvalue. Если вы случайно забыли предоставить эту информацию, тогда lvalues всегда возвращаются как lvalues и rvalues всегда возвращаются как rvalues. Хотя сначала это может звучать так, как вы хотите, это действительно не так.
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. Если автор factory случайно забыл поставить A1, использование identity
напоминает его во время компиляции.
Примечание. В окончательном проекте отсутствует identity
, но используется с тем же назначением remove_reference
для этой же цели.