Шаблон класса с вложенным объявлением класса (C ++) - PullRequest
1 голос
/ 28 января 2020

Учитывая, что шаблон класса называется Queue с вложенным классом Node (не шаблон класса):

template<typename T> 
class Queue {  

  private:

    struct Node {
        Node (T value) : value(value), next(nullptr) {}
        Node (T value, Node* next) : value(value), next(next) {}
        T value;
        Node* next;
    };

    Node* head;
    size_t sz;
    void cleanList();

  public:

    Queue();

    Queue(const Queue& st);
    Queue& operator=(const Queue& st);

    ~Queue();

    size_t size() const noexcept;
    bool isEmpty() const noexcept;

    T& front();
    const Tt& front() const;

    void enqueue(const T& elem);
    void dequeue(); 
};

Я могу сделать это:

template<typename T>
void Queue<T>::enqueue(const T& elem) {

    Node* temp = new Node(elem);

}

Это компилируется, но почему объявление Node не требует дополнительной информации? (как Queue::Node)


После прочтения Шаблоны и вложенные классы / структуры все 3 из них также работают и компилируются:

template<typename T>
void Queue<T>::enqueue(const T& elem) {

    typename LLQueue<Object>::Node* temp1 = new Node(elem);
    LLQueue<Object>::Node* temp2;
    LLQueue::Node* temp3;

}

Почему все версии работают? Что предпочтительнее при использовании вложенного класса в шаблоне класса?

1 Ответ

3 голосов
/ 28 января 2020

Он компилируется, но почему для объявления Node не требуется дополнительная информация?

Вот как происходит поиск безусловного имени в области действия функции-члена. Сначала компилятор проверяет область действия функции, ничего не находит, а затем переходит к области действия класса. В области видимости класса он видит Node, поэтому поиск имени выполняется успешно, и вы получаете тип Node, являющийся членом класса.

Почему все версии работают?

C ++ позволяет вам быть настолько явным, насколько вы хотите. Любое имя может быть полностью определено, и это то, что вы делаете. С typename LLQueue<Object>::Node, typename не нужен, но ничего не повредит. Это как struct foo{}; struct foo f; struct не нужно, но это разрешено грамматикой. Вторая строка с LLQueue<Object>::Node является менее явным способом и также допускается, поскольку typename фактически не требуется. LLQueue::Node работает, потому что в шаблоне класса class_name вводится в область видимости класса и это class_name<template_params>.

...