linked list template class doesn't compile

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • QiongZ
    New Member
    • Nov 2009
    • 7

    linked list template class doesn't compile

    Hi, I just recently started studying C++ and basically copied an example in the textbook into VS2008, but it doesn't compile. I tried to modify the code by eliminating all the templates then it compiled no problem. But I can't find the what the problem is with templates? Please help. The main is in test-linked-list.cpp. There are two template classes. One is List1, the other one is ListNode. The codes are below:


    Code:
    // test-linked-list.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include "list1.h"
    
    using std::cout;
    using std::cin;
    using std::endl;
    
    void testIntegerList();
    void instructions();
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	testIntegerList();
    	return 0;
    }
    
    void testIntegerList()
    {
    	cout << "Testing a List of integer values" << endl;
    
    	List1<int> integerList;
    
    	instructions();
    
    	int choice, value;
    
    	do {
    		cout << "? ";
    
    		cin >> choice;
    
    		switch (choice) {
    
    			case 1:
    				cout << "Enter an integer: ";
    				cin >> value;
    				integerList.insertAtFront(value);
    				integerList.print();
    				break;
    
    			case 2:
    				cout << "Enter an integer: ";
    				cin >> value;
    				integerList.insertAtBack(value);
    				integerList.print();
    				break;
    
    			case 3:
    				if (integerList.removeFromFront(value))
    					cout << "integer removed from front" << endl;
    				integerList.print();
    				break;
    
    			case 4:
    				if (integerList.removeFromBack(value))
    					cout << "integer removed from back" << endl;
    
    				integerList.print();
    				break;
    
    		}
    	} while (choice != 5);
    
    	cout << "End test of integer list" << endl;
    }
    
    void instructions()
    {
    	cout << "Enter one of the following:" << endl
    		<< " 1 to insert at beginning of list" << endl
    		<< " 2 to insert at the end of list" << endl
    		<< " 3 to delete from beginning of list" << endl
    		<< " 4 to delete from end of list" << endl
    		<< " 5 to end list processing" << endl;
    }
    
    // list1.h
    #ifndef LIST1_H
    #define LIST1_H
    
    #include "listnd.h"
    
    
    template<typename T>
    class List1 {
    public:
    	List1();
    	~List1();
    	void insertAtFront(T &);
    	void insertAtBack(T &);
    	int removeFromFront(T &);
    	int removeFromBack(T &);
    	int isEmpty();
    	void print();
    private:
    	ListNode<T> *firstPtr;
    	ListNode<T> *lastPtr;
    	ListNode<T> *getNewNode(T &);
    };
    
    
    #endif
    
    
    // list1.cpp
    #include "stdafx.h"
    #include "list1.h"
    #include <iostream>
    #include <assert.h>
    using std::cout;
    using std::endl;
    
    template<typename T>
    List1<T>::List1() {firstPtr = lastPtr = 0;}
    
    template<typename T>
    List1<T>::~List1()
    {
    	if (!isEmpty()) {
    		cout << "Destroying nodes ... " << endl;
    
    		ListNode<NODETYPE> *currentPtr = firstPtr, *tempPtr;
    		while (currentPtr != 0) {
    			tempPtr = currentPtr;
    			cout << tempPtr->data << endl;
    			currentPtr = currentPtr->nextPtr;
    			delete tempPtr;
    		}
    	}
    
    		cout << "All nodes destroyed" << endl << endl;
    }
    
    template<typename T>
    void List1<T>::insertAtFront(T &value)
    {
    	ListNode<NODETYPE> *newPtr = getNewNode(value);
    
    	newPtr->nextPtr = firstPtr;
    	firstPtr = newPtr;
    }
    
    template<typename T>
    void List1<T>::insertAtBack(T &value)
    {
    	ListNode<NODETYPE> *newPtr = getNewNode(value);
    
    	lastPtr->nextPtr = newPtr;
    	//newPtr->nextPtr = 0;
    	lastPtr = newPtr;
    }
    
    template<typename T>
    int List1<T>::removeFromFront(T &value)
    {
    	if (isEmpty())
    		return 0;
    	else {
    		ListNode<NODETYPE> *tempPtr = firstPtr;
    		if (firstPtr == lastPtr)
    			firstPtr = lastPtr = 0;
    		else
    			firstPtr = firstPtr->nextPtr;
    
    		value = tempPtr->data;
    		delete tempPtr;
    		return 1;
    	}
    }
    
    template<typename T>
    int List1<T>::removeFromBack(T &value)
    {
    	if (isEmpty())
    		return 0;
    	else {
    		ListNode<NODETYPE> *tempPtr = lastPtr;
    		if (firstPtr == lastPtr)
    			firstPtr = lastPtr = 0;
    		else {
    			ListNode<NODETYPE> *currentPtr = firstPtr;
    			while (currentPtr->nextPtr != lastPtr)
    				currentPtr = currentPtr->nextPtr;
    
    			lastPtr = currentPtr;
    			currentPtr->nextPtr = 0;
    		}
    
    		value = tempPtr-data;
    		delete tempPtr;
    		return 1;
    	}
    }
    
    template<typename T>
    int List1<T>::isEmpty() {return firstPtr == 0;}
    
    template<typename T>
    ListNode<NODETYPE> *List1<T>::getNewNode(T value)
    {
    	ListNode<NODETYPE> *ptr = new ListNode<NODETYPE>(value);
    
    	assert(ptr != 0);
    	return ptr;
    }
    
    template<typename T>
    void List1<T>::print()
    {
    	if (isEmpty()) {
    		cout << "The list is empty" << endl << endl;
    		return;
    	}
    
    	ListNode<NODETYPE> *currentPtr = firstPtr;
    
    	cout << "The list is: ";
    
    	while (currentPtr != 0) {
    		cout << currentPtr->data << ' ';
    		currentPtr = currentPtr->nextPtr;
    	}
    
    	cout << endl << endl;
    }
    
    // listnd.h
    #ifndef LISTND_H
    #define LISTND_H
    
    template<typename NODETYPE>
    class ListNode {
    	friend class List1<T>;
    	public: 
    		ListNode(NODETYPE &);
    		~ListNode();
    		NODETYPE getData();
    	private: 
    		NODETYPE data;			
    		ListNode *nextPtr;
    };
    
    #endif
    
    // listnd.cpp
    #include "stdafx.h"
    #include "listnd.h"
    
    template<typename NODETYPE>
    ListNode<NODETYPE>::ListNode(NODETYPE &info)
    {
    	data = info;
    	nextPtr = 0;
    }
    
    template<typename NODETYPE>
    NODETYPE ListNode<NODETYPE>::getData() {return data;}


    That's the codes. I get errors like the following:

    Code:
    1>Compiling...
    1>list1.cpp
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(6) : error C2059: syntax error : '<'
    1>        e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(14) : see reference to class template instantiation 'ListNode<NODETYPE>' being compiled
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(6) : error C2238: unexpected token(s) preceding ';'
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\list1.h(22) : error C2989: 'List1' : class template has already been declared as a non-class template
    1>        e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(6) : see declaration of 'List1'
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\list1.h(7) : error C3857: 'List1': multiple template parameter lists are not allowed
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\list1.cpp(9) : error C2988: unrecognizable template declaration/definition
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\list1.cpp(9) : error C2059: syntax error : '<'
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\list1.cpp(12) : error C2588: '::~List1' : illegal global destructor
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\list1.cpp(12) : fatal error C1903: unable to recover from previous error(s); stopping compilation
    1>listnd.cpp
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(6) : error C2059: syntax error : '<'
    1>        e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(14) : see reference to class template instantiation 'ListNode<NODETYPE>' being compiled
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(6) : error C2238: unexpected token(s) preceding ';'
    1>test-linked-list.cpp
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(6) : error C2059: syntax error : '<'
    1>        e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(14) : see reference to class template instantiation 'ListNode<NODETYPE>' being compiled
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(6) : error C2238: unexpected token(s) preceding ';'
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\list1.h(22) : error C2989: 'List1' : class template has already been declared as a non-class template
    1>        e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\listnd.h(6) : see declaration of 'List1'
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\list1.h(7) : error C3857: 'List1': multiple template parameter lists are not allowed
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(25) : error C2143: syntax error : missing ';' before '<'
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(25) : error C2143: syntax error : missing ';' before '<'
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(41) : error C2065: 'integerList' : undeclared identifier
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(41) : error C2228: left of '.insertAtFront' must have class/struct/union
    1>        type is ''unknown-type''
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(42) : error C2065: 'integerList' : undeclared identifier
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(42) : error C2228: left of '.print' must have class/struct/union
    1>        type is ''unknown-type''
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(48) : error C2065: 'integerList' : undeclared identifier
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(48) : error C2228: left of '.insertAtBack' must have class/struct/union
    1>        type is ''unknown-type''
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(49) : error C2065: 'integerList' : undeclared identifier
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(49) : error C2228: left of '.print' must have class/struct/union
    1>        type is ''unknown-type''
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(53) : error C2065: 'integerList' : undeclared identifier
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(53) : error C2228: left of '.removeFromFront' must have class/struct/union
    1>        type is ''unknown-type''
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(55) : error C2065: 'integerList' : undeclared identifier
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(55) : error C2228: left of '.print' must have class/struct/union
    1>        type is ''unknown-type''
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(59) : error C2065: 'integerList' : undeclared identifier
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(59) : error C2228: left of '.removeFromBack' must have class/struct/union
    1>        type is ''unknown-type''
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(62) : error C2065: 'integerList' : undeclared identifier
    1>e:\documents and settings\user\my documents\visual studio 2008\projects\test-linked-list\test-linked-list.cpp(62) : error C2228: left of '.print' must have class/struct/union
    1>        type is ''unknown-type''
    1>Generating Code...
    1>Build log was saved at "file://e:\Documents and Settings\user\My Documents\Visual Studio 2008\Projects\test-linked-list\Debug\BuildLog.htm"
    1>test-linked-list - 32 error(s), 0 warning(s)

    Thank you for taking time to look at this. I have been looking at this for a couple days now and really need some help here. Thank you!

    Qiong
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Which textbook are you using?

    There are so mnay errors in this example I can't believe it's in a book.

    Comment

    • QiongZ
      New Member
      • Nov 2009
      • 7

      #3
      C++ How to program by Deitel and Deitel.

      What kind of errors? Can you point out some of them for me? Thank you for your reply.

      One thing to note again: if I remove all the templates, the program compiled successfully.

      Qiong

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        I found the example. The Deitel book I have is dated 1994. That's before templates were actually working in C++.

        Further, you don't write linked lists in C++. Instead you use the C++ Standard Library list template.

        This book is so old that there was no C++ Standard Library. It didn't appear until 1998.

        In fact, all C++ books prior to September 1998 are pre-ANSI C++ and should be discarded.

        Get a newer book.

        In ANSI C++ a template is a pattern. When you specialize the template, the compiler makes a copy of it and replaces the typename placeholder with the actual type.

        Since the compiler needs to have the template in order ot make a copy, the template is a declaration and therefore all templates are placed in header files.

        The specializations are placed in the .cpp files.

        All this being said, it appears the example was not copied exactly into your computer. Like a typename of T appears whereas in the example everything is typename NODETYPE.

        I would make sure that all the temp[lates are in .h files. The only .cpp file you should have is the Driver.cpp file.


        Finally is appears your Visual Studio project is not set up correctly. You have a Windows console program and you really want a Console program without the Windows stuff.

        Do this:

        1) Create a Win32 application.
        2) When trhe wizard appears, DO NOT CLICK FINISH.
        3) Instead, click application settings.
        4) Select a) empty project and b) console application
        5) Now click FINISH.

        Post again if you are still stuck.

        Comment

        • QiongZ
          New Member
          • Nov 2009
          • 7

          #5
          Thank you very much for your reply. I made a few changes you suggested. I put templates all in header files and I am listing them again so that it is easy to see on which lines the errors occurred.

          linked-list-driver.cpp
          Code:
          // linked-list-driver.cpp : Defines the entry point for the console application.
          //
          
          //#include "stdafx.h"
          #include <iostream>
          #include "list1.h"
          
          using std::cout;
          using std::cin;
          using std::endl;
          
          void testIntegerList();
          void instructions();
          
          main()
          {
          	testIntegerList();
          	return 0;
          }
          
          void testIntegerList()
          {
          	cout << "Testing a List of integer values" << endl;
          
          	List1<int> integerList;
          
          	instructions();
          
          	int choice, value;
          
          	do {
          		cout << "? ";
          
          		cin >> choice;
          
          		switch (choice) {
          
          			case 1:
          				cout << "Enter an integer: ";
          				cin >> value;
          				integerList.insertAtFront(value);
          				integerList.print();
          				break;
          
          			case 2:
          				cout << "Enter an integer: ";
          				cin >> value;
          				integerList.insertAtBack(value);
          				integerList.print();
          				break;
          
          			case 3:
          				if (integerList.removeFromFront(value))
          					cout << "integer removed from front" << endl;
          				integerList.print();
          				break;
          
          			case 4:
          				if (integerList.removeFromBack(value))
          					cout << "integer removed from back" << endl;
          
          				integerList.print();
          				break;
          
          		}
          	} while (choice != 5);
          
          	cout << "End test of integer list" << endl;
          }
          
          void instructions()
          {
          	cout << "Enter one of the following:" << endl
          		<< " 1 to insert at beginning of list" << endl
          		<< " 2 to insert at the end of list" << endl
          		<< " 3 to delete from beginning of list" << endl
          		<< " 4 to delete from end of list" << endl
          		<< " 5 to end list processing" << endl;
          }

          list1.h
          Code:
          #ifndef LIST1_H
          #define LIST1_H
          
          //#include "stdafx.h"
          #include "listnd.h"
          #include <iostream>
          #include <assert.h>
          using std::cout;
          using std::endl;
          
          template<class T>
          class List1 {
          public:
          	List1();
          	~List1();
          	void insertAtFront(T &);
          	void insertAtBack(T &);
          	int removeFromFront(T &);
          	int removeFromBack(T &);
          	int isEmpty();
          	void print();
          private:
          	ListNode<T> *firstPtr;
          	ListNode<T> *lastPtr;
          	ListNode<T> *getNewNode(T &);
          };
          
          template<typename T>
          List1<T>::List1() {firstPtr = lastPtr = 0;}
          
          template<typename T>
          List1<T>::~List1()
          {
          	if (!isEmpty()) {
          		cout << "Destroying nodes ... " << endl;
          
          		ListNode<NODETYPE> *currentPtr = firstPtr, *tempPtr;
          		while (currentPtr != 0) {
          			tempPtr = currentPtr;
          			cout << tempPtr->data << endl;
          			currentPtr = currentPtr->nextPtr;
          			delete tempPtr;
          		}
          	}
          
          		cout << "All nodes destroyed" << endl << endl;
          }
          
          template<typename T>
          void List1<T>::insertAtFront(T &value)
          {
          	ListNode<NODETYPE> *newPtr = getNewNode(value);
          
          	newPtr->nextPtr = firstPtr;
          	firstPtr = newPtr;
          }
          
          template<typename T>
          void List1<T>::insertAtBack(T &value)
          {
          	ListNode<NODETYPE> *newPtr = getNewNode(value);
          
          	lastPtr->nextPtr = newPtr;
          	//newPtr->nextPtr = 0;
          	lastPtr = newPtr;
          }
          
          template<typename T>
          int List1<T>::removeFromFront(T &value)
          {
          	if (isEmpty())
          		return 0;
          	else {
          		ListNode<NODETYPE> *tempPtr = firstPtr;
          		if (firstPtr == lastPtr)
          			firstPtr = lastPtr = 0;
          		else
          			firstPtr = firstPtr->nextPtr;
          
          		value = tempPtr->data;
          		delete tempPtr;
          		return 1;
          	}
          }
          
          template<typename T>
          int List1<T>::removeFromBack(T &value)
          {
          	if (isEmpty())
          		return 0;
          	else {
          		ListNode<NODETYPE> *tempPtr = lastPtr;
          		if (firstPtr == lastPtr)
          			firstPtr = lastPtr = 0;
          		else {
          			ListNode<NODETYPE> *currentPtr = firstPtr;
          			while (currentPtr->nextPtr != lastPtr)
          				currentPtr = currentPtr->nextPtr;
          
          			lastPtr = currentPtr;
          			currentPtr->nextPtr = 0;
          		}
          
          		value = tempPtr-data;
          		delete tempPtr;
          		return 1;
          	}
          }
          
          template<typename T>
          int List1<T>::isEmpty() {return firstPtr == 0;}
          
          template<typename T>
          ListNode<NODETYPE> *List1<T>::getNewNode(T value)
          {
          	ListNode<NODETYPE> *ptr = new ListNode<NODETYPE>(value);
          
          	assert(ptr != 0);
          	return ptr;
          }
          
          template<typename T>
          void List1<T>::print()
          {
          	if (isEmpty()) {
          		cout << "The list is empty" << endl << endl;
          		return;
          	}
          
          	ListNode<NODETYPE> *currentPtr = firstPtr;
          
          	cout << "The list is: ";
          
          	while (currentPtr != 0) {
          		cout << currentPtr->data << ' ';
          		currentPtr = currentPtr->nextPtr;
          	}
          
          	cout << endl << endl;
          }
          
          #endif

          listnd.h
          Code:
          #ifndef LISTND_H
          #define LISTND_H
          
          //#include "stdafx.h"
          
          template<typename NODETYPE>
          class ListNode {
          	friend class List1<T>;
          	public: 
          		ListNode(NODETYPE &);
          		~ListNode();
          		NODETYPE getData();
          	private: 
          		NODETYPE data;			
          		ListNode *nextPtr;
          };
          
          template<typename NODETYPE>
          ListNode<NODETYPE>::ListNode(NODETYPE &info)
          {
          	data = info;
          	nextPtr = 0;
          }
          
          template<typename NODETYPE>
          NODETYPE ListNode<NODETYPE>::getData() {return data;}
          
          #endif

          I got fewer errors this time:

          listnd.h(8) : error C2059: syntax error : '<'
          listnd.h(16) : see reference to class template instantiation 'ListNode<NODET YPE>' being compiled
          listnd.h(8) : error C2238: unexpected token(s) preceding ';'
          list1.h(26) : error C2989: 'List1' : class template has already been declared as a non-class template
          listnd.h(8) : see declaration of 'List1'
          list1.h(11) : error C3857: 'List1': multiple template parameter lists are not allowed
          list1.h(29) : error C2988: unrecognizable template declaration/definition
          list1.h(29) : error C2059: syntax error : '<'
          list1.h(32) : error C2588: '::~List1' : illegal global destructor
          list1.h(32) : fatal error C1903: unable to recover from previous error(s); stopping compilation

          Qiong

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            This cose os your first error:

            Code:
             friend class List1<T>;
            I suggest you research bound vs. unbound friends in templates.

            The C++ Primer Plus 5th edition has a good explanantion. And there is Google.

            Comment

            • QiongZ
              New Member
              • Nov 2009
              • 7

              #7
              The problem is solved. Someone suggested me to add

              Code:
              template< typename T > class List1;
              in listnd.h before declaration of ListNode.

              And also I did the following two things:

              1 took destructor ~ListNode() out of listnd.h
              2. make sure all the typename (for class List1 and class ListNode) same


              that did the trick.

              Thank you very much for your help, weaknessforcats . Hope this post can help someone else in the future.

              Qiong

              Comment

              • wysiswyg
                New Member
                • Apr 2010
                • 1

                #8
                Hello

                Hi Qiong,

                Can you give me the correct code, using your program I am still getting the following errors at compile time.

                linked-list-driver.cpp
                c:\program files\microsoft visual studio 8\vc\list1.h(11 4) : error C2065: 'NODET
                YPE' : undeclared identifier
                c:\program files\microsoft visual studio 8\vc\list1.h(12 0) : error C2244: 'List1
                <T>::getNewNode ' : unable to match function definition to an existing declaratio
                n
                c:\program files\microsoft visual studio 8\vc\list1.h(25 ) : see declarat
                ion of 'List1<T>::getN ewNode'
                definition
                'ListNode *List1<T>::getN ewNode(T)'
                existing declarations
                'ListNode<NODET YPE> *List1<T>::getN ewNode(T &)'

                Comment

                Working...