How can I make a template class within a template class

360 views Asked by At

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>
      | 
2

There are 2 answers

0
Nathan Pierson On BEST ANSWER

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.

2
BoP On

In the first case, the node is forward_list<T>::node, or just node within the list. There is no node<T>.

In the second case, the problem is that you have two templates both named T when you probably wanted two different templates.

So give them different names. :-)

template <class T>
class forward_list
{
        template <class U> 
        class node
        {
        };
};