1

Given that a class template called Queue with a nested class Node (not a class template):

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(); 
};

I can do this:

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

    Node* temp = new Node(elem);

}

It compiles, but why does declaring a Node not need more information? (like Queue::Node)


After reading Templates and nested classes/structures, all 3 of these also works and compiles:

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;

}

Why do all versions work? Which is preferred when using a nested class in a class template?

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
csguy
  • 1,354
  • 2
  • 17
  • 37

1 Answers1

3

It compiles, but why does declaring a Node not need more information?

This is how unqualified name lookup happens in a member function scope. First the compiler checks the scope of the function, doesn't find anything, and then moves on to the class scope. In the class scope it sees Node, so name lookup succeeds and you get the Node type that is a member of the class.

Why do all versions work?

C++ lets you be as explicit as you want to be. Any name can be fully qualified and that is what you are doing. With typename LLQueue<Object>::Node, the typename isn't needed, but it doesn't hurt anything. Its like doing struct foo{}; struct foo f; the struct isn't needed but it is allowed by the grammar. The second line with LLQueue<Object>::Node is just a less explicit way and also allowed since typename isn't actually required. LLQueue::Node works because in a class template class_name is injected into the class scope and it is class_name<template_params>.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402