Официально, что такое имя типа для?

Если вы используете Objective C, вам нужно использовать классы NSURL, NSURLRequest и NURLConnection. Документ NSURLRequest от Apple . HttpRequest для JavaScript.

116
задан dicroce 21 October 2009 в 13:45
поделиться

6 ответов

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.

186
ответ дан 24 November 2019 в 02:15
поделиться

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!
    .
    .
13
ответ дан 24 November 2019 в 02:15
поделиться

Сообщение Стэна Липпмана в блоге предлагает: -

Страуструп повторно использовал существующий класс ключевое слово для указания параметра типа вместо того, чтобы вводить новое ключевое слово это, конечно, может сломать существующие программы. Это было не новое ключевое слово не рассматривался - просто это не считалось необходимым, учитывая его потенциальный сбой. И до 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

35
ответ дан 24 November 2019 в 02:15
поделиться

Two uses:

  1. As a template argument keyword (instead of 'class')
  2. A typename keyword tells the compiler that an identifier is a type (rather than a static member variable)
template  class X // [1]
{
 typename T::Y _member; // [2] 
}
4
ответ дан 24 November 2019 в 02:15
поделиться

В некоторых ситуациях, когда вы ссылаетесь на член так называемого зависимого типа (что означает «зависит от параметра шаблона»), компилятор не всегда может однозначно вывести семантическое значение результирующей конструкции, потому что это не так. Я не знаю, что это за имя (т.е. является ли это именем типа, именем элемента данных или именем чего-то еще). В подобных случаях вы должны устранить неоднозначность ситуации, явно указав компилятору, что имя принадлежит типу, определенному как член этого зависимого типа.

Например

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 должна использоваться в объявлениях параметров шаблона.

6
ответ дан 24 November 2019 в 02:15
поделиться

Секрет заключается в том, что шаблон может быть специализирован для некоторых типов. Это означает, что он также может определять интерфейс совершенно по-разному для нескольких типов. Например, вы можете написать:

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 :: ptr является типом. Но компилятор не знает, и на самом деле стандарт даже советует ему ожидать обратного, test :: ptr не является типом. Чтобы сообщить компилятору, чего вы ожидаете, вы должны перед этим добавить typename . Правильный шаблон выглядит так

template<typename T>
void print(T& x) {
    typename test<T>::ptr p = &x;
    std::cout << *p << std::endl;
}

Итог: Вы должны добавить typename перед тем, как будете использовать вложенный тип шаблона в своих шаблонах. (Конечно, только если параметр шаблона вашего шаблона используется для этого внутреннего шаблона.)

5
ответ дан 24 November 2019 в 02:15
поделиться
Другие вопросы по тегам:

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