Если вы используете Objective C, вам нужно использовать классы NSURL, NSURLRequest и NURLConnection. Документ NSURLRequest от Apple . HttpRequest для JavaScript.
Following is the quote from Josuttis book:
The keyword typename was introduced to specify that the identifier that follows is a type. Consider the following example:
template
Class MyClass { typename T::SubType * ptr; ... }; Here, typename is used to clarify that SubType is a type of class T. Thus, ptr is a pointer to the type T::SubType. Without typename, SubType would be considered a static member. Thus
T::SubType * ptr
would be a multiplication of value SubType of type T with ptr.
Consider the code
template<class T> somefunction( T * arg )
{
T::sometype x; // broken
.
.
Unfortunately, the compiler is not required to be psychic, and doesn't know whether T::sometype will end up referring to a type name or a static member of T. So, one uses typename
to tell it:
template<class T> somefunction( T * arg )
{
typename T::sometype x; // works!
.
.
Сообщение Стэна Липпмана в блоге предлагает: -
Страуструп повторно использовал существующий класс ключевое слово для указания параметра типа вместо того, чтобы вводить новое ключевое слово это, конечно, может сломать существующие программы. Это было не новое ключевое слово не рассматривался - просто это не считалось необходимым, учитывая его потенциальный сбой. И до ISO-C++ standard, this was the only way to declare a type parameter.
So basically Stroustrup reused class keyword without introducing a new keyword which is changed afterwards in the standard for the following reasons
As the example given
template <class T>
class Demonstration {
public:
void method() {
T::A *aObj; // oops …
// …
};
language grammar misinterprets T::A *aObj;
as an arithmetic expression so a new keyword is introduced called typename
typename T::A* a6;
it instructs the compiler to treat the subsequent statement as a declaration.
Since the keyword was on the payroll, heck, why not fix the confusion caused by the original decision to reuse the class keyword.
Thats why we have both
You can have a look at this post, it will definitely help you, I just extracted from it as much as I could
Two uses:
template
class X // [1] { typename T::Y _member; // [2] }
В некоторых ситуациях, когда вы ссылаетесь на член так называемого зависимого типа (что означает «зависит от параметра шаблона»), компилятор не всегда может однозначно вывести семантическое значение результирующей конструкции, потому что это не так. Я не знаю, что это за имя (т.е. является ли это именем типа, именем элемента данных или именем чего-то еще). В подобных случаях вы должны устранить неоднозначность ситуации, явно указав компилятору, что имя принадлежит типу, определенному как член этого зависимого типа.
Например
template <class T> struct S {
typename T::type i;
};
В этом примере ключевое слово typename
необходимо для компиляции кода.
То же самое происходит, когда вы хотите сослаться на член шаблона зависимого типа, то есть на имя, обозначающее шаблон. Вы также должны помочь компилятору, используя ключевое слово template
, хотя оно размещено по-другому
template <class T> struct S {
T::template ptr<int> p;
};
В некоторых случаях может потребоваться использовать оба
template <class T> struct S {
typename T::template ptr<int>::type i;
};
(если я правильно понял синтаксис).
Конечно, другая роль ключевого слова typename
должна использоваться в объявлениях параметров шаблона.
Секрет заключается в том, что шаблон может быть специализирован для некоторых типов. Это означает, что он также может определять интерфейс совершенно по-разному для нескольких типов. Например, вы можете написать:
template<typename T>
struct test {
typedef T* ptr;
};
template<> // complete specialization
struct test<int> { // for the case T is int
T* ptr;
};
Кто-то может спросить, почему это полезно и действительно: это действительно выглядит бесполезным. Но учтите, например, что std :: vector
тип ссылки
выглядит совершенно иначе, чем для других T
s. По общему признанию, это не меняет вид ссылки
с типа на что-то другое, но, тем не менее, это может произойти.
Что произойдет, если вы напишете свои собственные шаблоны, используя этот тестовый
шаблон . Что-то вроде этого
template<typename T>
void print(T& x) {
test<T>::ptr p = &x;
std::cout << *p << std::endl;
}
кажется вам приемлемым, потому что вы ожидаете , что test
является типом. Но компилятор не знает, и на самом деле стандарт даже советует ему ожидать обратного, test
не является типом. Чтобы сообщить компилятору, чего вы ожидаете, вы должны перед этим добавить typename
. Правильный шаблон выглядит так
template<typename T>
void print(T& x) {
typename test<T>::ptr p = &x;
std::cout << *p << std::endl;
}
Итог: Вы должны добавить typename
перед тем, как будете использовать вложенный тип шаблона в своих шаблонах. (Конечно, только если параметр шаблона вашего шаблона используется для этого внутреннего шаблона.)