Зачем использовать идентичность в прямом определении для ссылки на C ++ 0x? - PullRequest
20 голосов
/ 01 апреля 2011

In Краткое введение в Rvalue References , 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 Ответ

18 голосов
/ 01 апреля 2011

Целью 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 в том же месте длята же цель.

...