Зачем использовать идентичность в прямом определении для ссылки на C++0x?
В кратком введении в Rvalue Ссылки, forward
определяется следующим образом:
template <typename T>
struct identity { typedef T type; };
template <typename T>
T &&forward(typename identity<T>::type &&a) { return a; }
Какую цель делает identity
класс выступать? Почему бы и нет:
template <typename T>
T &&forward(T &&a) { return a; }
1 ответ
Цель 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
возвращается как значение. Если автор фабрики случайно забудет поставить А1, использование identity
напоминает ему во время компиляции.
Примечание: в окончательном варианте отсутствует identity
, но использует remove_reference
в том же месте для той же цели.