Почему вам иногда нужно писать `typename T` вместо просто` T`?

Запрос GET зашифрован при использовании HTTPS - на самом деле именно поэтому защищенные веб-сайты должны иметь уникальный IP-адрес - нет способа получить требуемое имя хоста (или виртуальный каталог) из запроса до тех пор, пока оно не будет расшифровано.

10
задан StackedCrooked 8 February 2014 в 06:33
поделиться

3 ответа

В общем, синтаксис C ++ (унаследованный от C) имеет технический дефект: синтаксический анализатор ДОЛЖЕН знать, называет ли что-то тип или нет, иначе он просто не сможет разрешить некоторые неоднозначности (например, X * Y умножение или объявление указателя Y на объекты типа X? все зависит от того, называет ли X тип ...! -). typename «прилагательное» позволяет вам сделать это совершенно ясным и явным, когда это необходимо (что, как упоминается в другом ответе, типично, когда задействованы параметры шаблона; -).

9
ответ дан 3 December 2019 в 16:30
поделиться

Краткая версия, которую вам нужно сделать typename X :: Y всякий раз, когда X является параметром шаблона или зависит от него. Пока X не известен, компилятор не может определить, является ли Y типом или значением. Поэтому вам нужно добавить typename , чтобы указать, что это тип.

Например:

template <typename T>
struct Foo {
  typename T::some_type x; // T is a template parameter. `some_type` may or may not exist depending on what type T is.
};

template <typename T>
struct Foo {
  typename some_template<T>::some_type x; // `some_template` may or may not have a `some_type` member, depending on which specialization is used when it is instantiated for type `T`
};

Как sbi указывает в комментариях, причина неоднозначности в том, что Y может быть статическим членом, перечислением или функцией. Не зная тип X , мы не можем сказать. Стандарт указывает, что компилятор должен предполагать, что это значение, если он явно не помечен как тип с помощью ключевого слова typename .

И похоже, что комментаторы действительно хотят, чтобы я упомянул еще один связанный случай:;)

Если зависимое имя является шаблоном члена функции, и вы вызываете его с явным аргументом шаблона ( foo. bar () , например), вы должны добавить ключевое слово template перед именем функции, как в foo.template bar () .

Причина этого в том, что без ключевого слова template компилятор предполагает, что bar является значением, и вы хотите вызвать для него оператор «меньше» ( operator <). .

13
ответ дан 3 December 2019 в 16:30
поделиться

По сути, вам нужно ключевое слово typename , когда вы пишете код шаблона (т.е. вы находитесь в шаблоне функции или шаблоне класса), и вы имеете в виду идентификатор, который зависит от для параметра шаблона, который может быть неизвестен как тип, но должен интерпретироваться как тип в вашем коде шаблона.

В вашем примере вы используете typename T :: Type в определении # 1 потому что T :: Type зависит от параметра шаблона T и в противном случае может быть членом данных.

Вам не нужно typename T в определении # 2 как T объявлен как тип как часть определения шаблона.

3
ответ дан 3 December 2019 в 16:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: