Запрос GET зашифрован при использовании HTTPS - на самом деле именно поэтому защищенные веб-сайты должны иметь уникальный IP-адрес - нет способа получить требуемое имя хоста (или виртуальный каталог) из запроса до тех пор, пока оно не будет расшифровано.
В общем, синтаксис C ++ (унаследованный от C) имеет технический дефект: синтаксический анализатор ДОЛЖЕН знать, называет ли что-то тип или нет, иначе он просто не сможет разрешить некоторые неоднозначности (например, X * Y
умножение или объявление указателя Y на объекты типа X? все зависит от того, называет ли X тип ...! -). typename
«прилагательное» позволяет вам сделать это совершенно ясным и явным, когда это необходимо (что, как упоминается в другом ответе, типично, когда задействованы параметры шаблона; -).
Краткая версия, которую вам нужно сделать 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 <
). .
По сути, вам нужно ключевое слово typename
, когда вы пишете код шаблона (т.е. вы находитесь в шаблоне функции или шаблоне класса), и вы имеете в виду идентификатор, который зависит от для параметра шаблона, который может быть неизвестен как тип, но должен интерпретироваться как тип в вашем коде шаблона.
В вашем примере вы используете typename T :: Type
в определении # 1 потому что T :: Type
зависит от параметра шаблона T
и в противном случае может быть членом данных.
Вам не нужно typename T
в определении # 2 как T
объявлен как тип как часть определения шаблона.