Page 1 of 1

using a template class inside another template class in C++

Posted: Thu Oct 02, 2008 6:01 pm
by smitty5658
I'm currently writing a linked list template class that uses a node template class. The node template works great but when I try to run the linked list template, my compiler complains that node is not a type even though I included the node header in the linked list header. I was curious if there is a restriction on nesting template classes like this that I wasn't aware of. Thanks in advance.

Re: using a template class inside another template class in C++

Posted: Thu Oct 02, 2008 7:49 pm
by pcmattman
Are you able to post some code? It's far easier to help if we can see what you've written.

Re: using a template class inside another template class in C++

Posted: Thu Oct 02, 2008 8:19 pm
by smitty5658
That's no problem. I appreciate the response.
FYI the node class is called element and the compiler error occurs in the linked_list.template insertion functions saying
'element' is not a type
element.h

Code: Select all

#ifndef _ELEMENT_H
#define _ELEMENT_H

template <class Item>
class element
{
    public:
        element(Item new_element_data); //constructor
        Item get_element_data(); //returns element data
        void set_element_data(Item new_element_data); //updates element data
        element<Item>* get_previous_element(); //returns a pointer to the previous element in the list
        element<Item>* get_next_element(); //returns a pointer to the next pointer in the list
        void set_next_element(element<Item>* new_next_element); //updates the pointer to the next element
        void set_previous_element(element<Item>* new_prev_element); //updates the pointer to the previous element
    private:
        Item element_data; //element data
        element<Item>* next_element; //pointer to the next element in the list
        element<Item>* previous_element; //pointer to the previous element in the list
};

#include "element.template"
#endif
element.template

Code: Select all

template <class Item>
element<Item>::element(Item new_element_data)
{
    element_data = new_element_data;
    previous_element = NULL;
    next_element = NULL;
}

template <class Item>
Item element<Item>::get_element_data()
{
    return element_data;
}

template <class Item>
void element<Item>::set_element_data(Item new_element_data)
{
    element_data = new_element_data;
}

template <class Item>
element<Item>* element<Item>::get_previous_element()
{
    return previous_element;
}

template <class Item>
element<Item>* element<Item>::get_next_element()
{
    return next_element;
}

template <class Item>
void element<Item>::set_previous_element(element<Item>* new_previous_element)
{
    previous_element = new_previous_element;
    if (new_previous_element->get_next_element() != this)
        new_previous_element->set_next_element(this);
}

template <class Item>
void element<Item>::set_next_element(element<Item>* new_next_element)
{
    next_element = new_next_element;
    if (new_next_element->get_previous_element() != this)
        new_next_element->set_previous_element(this);
}
linked_list.h

Code: Select all

#ifndef _LINKED_LIST_H
#define _LINKED_LIST_H
#include "element.h"

template <class Item>
class linked_list
{
    public:
        unsigned list_length(); //returns the number of elements in the list
        void delete_element(element<Item>* element_address); //deletes the given element and restores chain of links between elements
        element<Item>* find_element_pointer(element<Item>* element_address); 
        Item return_head_element_data(); //returns the data in the element at the head of the list
        Item return_tail_element_data(); //returns the data in the element at the tail of the list
        void insert_new_head_element(const Item& new_element_data); //inserts a new head element 
        void insert_new_element(element<Item>* new_element_position, const Item& new_element_data); //inserts a element in the list
        void insert_new_tail_element(const Item& new_element_data); //inserts a new tail element
        element<Item>* find_element_data(const Item& data); //returns a pointer to the element whose data matches the parameter
    private:
        element<Item>* head_element; //pointer to the "head" element
        element<Item>* tail_element; //pointer to the "tail" element
};

#include "linked_list.template"
#endif
linked_list.template

Code: Select all

template <class Item>
unsigned linked_list<Item>::list_length()
{
    if (head_element == NULL)
        return 0;
    else
    {
        element<Item>* current_element = head_element;
        int i;
        for (i = 1; current_element->get_next_element() != NULL; ++i)
            current_element = current_element->get_element_link();
        return i;
    }       
}

template <class Item>
void linked_list<Item>::delete_element(element<Item>* element_address)
{
    if (element_address == NULL)
        return;
    if (element_address->get_next_element() != NULL)
        element_address->get_next_element()->set_previous_element(element_address->get_previous_element());
    if (element_address->get_previous_element() != NULL)
        element_address->get_previous_element()->set_next_element(element_address->get_next_element());
    delete element_address;
}

template <class Item>
element<Item>* linked_list<Item>::find_element_pointer(element<Item>* element_address)
{
    if (element_address == NULL)
        return NULL;
    element<Item>* i;
    for(i = head_element; i != NULL; i = i->get_next_element())
    {
        if (i == element_address)
            return i;
    }
    return NULL;
}

template <class Item>
Item linked_list<Item>::return_head_element_data()
{
    return head_element->get_element_data();
}

template <class Item>
Item linked_list<Item>::return_tail_element_data()
{
    return tail_element->get_element_data();
}

template <class Item>
void linked_list<Item>::insert_new_head_element(const Item& new_element_data)
{
    element<Item> e1 = new element(new_element_data);
    e1.set_next_element(head_element);
    head_element = &e1;
}

template <class Item>
void linked_list<Item>::insert_new_element(element<Item>* previous_element, const Item& new_element_data)
{
    if (previous_element == NULL || previous_element == tail_element)
        return insert_new_tail_element(new_element_data);
    element<Item> e1 = new element(new_element_data);
    if (previous_element->get__next_element() != NULL)
    {
        e1.set_next_element(previous_element->get_next_element());
        e1.get_next_element()->set_previous_element(&e1);
    }
    previous_element->set_element_link(&e1);
}

template <class Item>
void linked_list<Item>::insert_new_tail_element(const Item& new_element_data)
{
    element<Item> e1 = new element(new_element_data);
    tail_element->set_next_element(&e1);
    tail_element = &e1;
}

template <class Item>
element<Item>* linked_list<Item>::find_element_data(const Item& data)
{
    element<Item>* i;
    for(i = head_element; i != NULL; i = i->get_next_element())
    {
        if (i->get_element_data() == data)
            return i;
    }
    return NULL;
}
I apologize for the lack of comments in the template files in advance

Re: using a template class inside another template class in C++

Posted: Thu Oct 02, 2008 8:38 pm
by pcmattman
I assume you use G++. Visual C++ 2005 (not the express edition) compiles the code properly - but there's a lot of bugs and mistakes (so I never actually got to a working state). Of course, VC++ allows you to get away with a bit more than G++ does.

Do you mind posting the code which you use to test? It shouldn't be failing until you actually try to use a template anyway, so it'd be nice to see the code you use.

Re: using a template class inside another template class in C++

Posted: Thu Oct 02, 2008 8:54 pm
by smitty5658
BTW I'm using Dev C++
I haven't written an actual testing function for the linked list yet because the template can't pass the syntax checker feature of my compiler. I have been using a blank main function with an include to the linked list header. If you would like, I can post that but I don't think it will be useful.
I'm not sure if this will help but I plan on using the linked list in implementing a stack template in lieu of an array.

Re: using a template class inside another template class in C++

Posted: Thu Oct 02, 2008 10:38 pm
by pcmattman
Would you mind copying and pasting the exact error(s)?

Re: using a template class inside another template class in C++

Posted: Fri Oct 03, 2008 6:27 am
by smitty5658
No problem here's the compiler messages

Code: Select all

3 C:\Users\Jason\Documents\CECS302\New Folder\linked_list.h:23,               
from main.cpp In file included from linked_list.h:23,               
from main.cpp 
 C:\Users\Jason\Documents\CECS302\New Folder\linked_list.template In member function `void linked_list<Item>::insert_new_head_element(const Item&)': 
57 C:\Users\Jason\Documents\CECS302\New Folder\linked_list.template `element' is not a type 
 C:\Users\Jason\Documents\CECS302\New Folder\linked_list.template In member function `void linked_list<Item>::insert_new_element(element<Item>*, const Item&)': 
67 C:\Users\Jason\Documents\CECS302\New Folder\linked_list.template `element' is not a type 
 C:\Users\Jason\Documents\CECS302\New Folder\linked_list.template In member function `void linked_list<Item>::insert_new_tail_element(const Item&)': 
79 C:\Users\Jason\Documents\CECS302\New Folder\linked_list.template `element' is not a type 
 C:\Users\Jason\Documents\CECS302\New Folder\Makefile.win [Build Error] n\make.exe: *** [main.o] Error 1 
Thanks again for your time

Re: using a template class inside another template class in C++

Posted: Fri Oct 03, 2008 6:49 am
by AJ
Hi,

For the first error in "insert_new_head_element(const Item&)":

Code: Select all

 element<Item> e1 = new element(new_element_data);
Shouldn't this be:

Code: Select all

 element<Item> e1 = new element<Item>(new_element_data);
?

And it looks like the other messages are in a similar vein...

Cheers,
Adam

Re: using a template class inside another template class in C++

Posted: Fri Oct 03, 2008 7:59 am
by smitty5658
that fixed it
thanks guys