Нужна помощь в понимании этой статьи о шаблонах - PullRequest
2 голосов
/ 02 сентября 2011

Я читал эту статью с этой страницы , поэтому позвольте мне представить код:

template <class T> class D: typename C<T>::Base { //#1 error
    D(): typename C<T>::Base(typename C<T>::Base(0)) { } //#2 error, #3 correct
    typename C<T> f() { //#4 error
        typename C<T>::A* p; //#5 correct
        A<T>::B * n;
    }
};
class Q{
    typename C<long>::A * p; // #6 error
}
template <class T, class U> class R{
    typename C<long>::A * p; // #7 optional
}

#3 правильно, но я пытаюсь понять, что автор пытается передать. Он говорит:

typename # 3: правильно. Здесь typename используется для устранения неоднозначности тип параметра . Без typename, выражение C :: Base (0) будет рассматриваться как вызов функции с именем Base. С префикс typename, C :: Base (0) создает временный объект типа C :: Base инициализируется с аргументом 0.

Кроме того, если вы видите немного выше этой части, автор говорит:

Ключевое слово typename должно содержать префикс зависимого имени, когда это имя удовлетворяет следующим трем правилам:

1.Это появляется внутри шаблона

2. Он квалифицирован // я вообще не могу понять эту строку в связи с начальным пунктом этой цитаты

3.Не используется в спецификации базового класса или инициализации члена список.

Я не могу понять эту строку (# 2 выше) вообще в связи с начальным абзацем этой цитаты. Можете ли вы объяснить, что автор имеет в виду?

Ответы [ 2 ]

2 голосов
/ 02 сентября 2011

«Квалифицированный» означает, что он находится не в той же области, а в текущей области, которая также зависит от шаблона.Например,

template <class T> struct C {
    typedef int b;
}

b является квалифицированным id при ссылке в другом шаблоне, например,

template<typename T> struct M {
    typename C<T>::b bb;
}

Соответствующая цитата из стандарта (§14.6.3):

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

И §14.6.2:

A name used in a template declaration or definition and that is dependent on a template-parameter is
assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified
by the keyword typename. [Example:
    // no B declared here
    class X;
    template<class T> class Y {
        class Z; // forward declaration of member class
        void f() {
            X* a1; // declare pointer to X
            T* a2; // declare pointer to T
            Y* a3; // declare pointer to Y<T>
            Z* a4; // declare pointer to Z
            typedef typename T::A TA;
            TA* a5; // declare pointer to T’s A
            typename T::A* a6; // declare pointer to T’s A
            T::A* a7; // T::A is not a type name:
            // multiply T::A by a7; ill-formed,
            // no visible declaration of a7
            B* a8; // B is not a type name:
            // multiply B by a8; ill-formed,
            // no visible declarations of B and a8
        }
    };
—end example]

И §14.6.7:

Within the definition of a class template or within the definition of a member of a class template, the keyword
typename is not required when referring to the unqualified name of a previously declared member
of the class template that declares a type. The keyword typename shall always be specified when the
member is referred to using a qualified name, even if the qualifier is simply the class template name.
[Example:
    template<class T> struct A {
        typedef int B;
        A::B b; // ill-formed: typename required before A::B
        void f(A<T>::B); // ill-formed: typename required before A<T>::B
        typename A::B g(); // OK
    };

The keyword typename is required whether the qualified name is A or A<T> because A or A<T> are synonyms
within a class template with the parameter list <T>. ]
0 голосов
/ 02 сентября 2011

Не уверен, что это может помочь, но пример использования шаблона:

template<typename TemplateVar>
class SimpleTemplate
{
    public:
        TemplateVar Item;

        void SetItem(TemplateVar &ItemCopy);
        TemplateVar &GetItem();
};

template<typename TemplateVar>
void SimpleTemplate<TemplateVar>::SetItem(TemplateVar &ItemCopy)
{
    Item = ItemCopy;
    return;
}

template<typename TemplateVar>
TemplateVar &SimpleTemplate<TemplateVar>::GetItem()
{
    return Item;
}

int main(int ArgC, char *ArgV[])
{
    SimpleTemplate<char> Test;
    return 0;
}

Не стесняйтесь делать с кодом все, что вы хотите (даже продавать, если можете).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...