c++classtemplatestemplate-classes

How can I make a template class within a template class


I am working on recreating the forward linked list class so I can better understand pointers. I have hit a roadblock, I have a template class called forward_list. Within this class in the private section I have another class which I want to have the same type as the main (external) class, this class is called node.

#ifndef FORWARD_LIST_HPP
#define FORWARD_LIST_HPP

template <class T>
class forward_list
{
    private:
        class node
        {
            T data;
            node<T>* next;
        };
        node<T>* head, tail;
    public:
        forward_list();
        ~forward_list();
        void pushBack(T t);
        void print();
};

#endif

When I compile the above code with the rest of my code I produce this error:

./forward_list.hpp:11:19: error: non-template type ‘node’ used as a template
   11 |             node<T>* next;
      |  

I also have tried this (I will add a '*' on the line I have added.)

#ifndef FORWARD_LIST_HPP
#define FORWARD_LIST_HPP

template <class T>
class forward_list
{
    private:
        template <class T>   // *
        class node
        {
            T data;
            node<T>* next;
        };
        node<T>* head, tail;
    public:
        forward_list();
        ~forward_list();
        void pushBack(T t);
        void print();
};

#endif

Here is the error this change has produced:

./forward_list.hpp:8:19: error: declaration of template parameter ‘T’ shadows template parameter
    8 |         template <class T>
      | 

Solution

  • Your first example is pretty close to what you want. The thing to realize is that while forward_list is a class template, forward_list<T> is a class, and forward_list<T>::node is also a class, not a class template. But also forward_list<int>::node is a totally separate class from forward_list<double>::node, even though they're both just called node.

    So, the following would work:

    template <class T>
    class forward_list
    {
        private:
            class node
            {
                T data;
                node* next; // Just node*, not node<T>*
            };
            node* head, tail; // Just node*, not node<T>*
        public:
            forward_list();
            ~forward_list();
            void pushBack(T t);
            void print();
    };
    

    This way forward_list<int> will have a nested class forward_list<int>::node with an int data; member variable, and forward_list<double> will have a nested class forward_list<double>::node with a double data; member variable.