Зачем использовать идентичность в прямом определении для ссылки на 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 в том же месте для той же цели.

Другие вопросы по тегам