Error on template functions returning pointers

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • edyam
    New Member
    • Dec 2007
    • 8

    Error on template functions returning pointers

    I'm trying to template a pointer-based list class and several functions (the ones in which I try to return a pointer) are producing error messages.

    The class:

    Code:
    template <typename T>
    class List : public BasicADT
    {
    	public:
    		
    		List();     // constructor
    		List(const List<T>& aList);	// copy constructor
    		virtual ~List();	// destructor
    		
    		// overloaded assignment operator
    		List<T> & operator=(const List<T>& rhs);
    		
    		// member functions
    		virtual bool isEmpty() const;
    		virtual int getLength() const;
    		virtual void insert(int index, const T& newItem);
    		virtual void remove(int index);
    		virtual void retrieve(int index, T& dataItem) const;
    		virtual void removeAll();
    		
    	private: 
    	
    		struct ListNode
    		{
    			T item;
    			ListNode *next;
    		};	// end ListNode
    		
    		int size;
    		ListNode *head;
    		ListNode *find(int index) const;
    		void copyListNodes(List<T> origList);
    		
    	protected:
    	
    		void setSize(int newSize);
    		ListNode *getHead() const;
    		void setHead(ListNode *ptr) const;
    		T getNodeItem(ListNode *ptr) const;
    		ListNode *getNextNode(ListNode *ptr) const;
    		
    } ;	// end List
    The functions:

    Code:
    template <typename T>
    ListNode *List<T>::find(int index) const
    {
    	if ( (index < 1) || (index > getLength()) )
    	{
    		return null;
    	}
    	
    	else
    	{
    		ListNode *cur = head;
    		
    		for (int skip = 1; skip < index; ++skip)
    		{
    			cur = cur->next;
    		}	// end for
    		
    		return cur;
    	}	// end if	
    }	// end find
    
    template <typename T>
    ListNode *List<T>::getHead() const
    {
    	return head;
    
    }	// end getHead
    
    template <typename T>
    ListNode *List<T>::getNextNode(ListNode *ptr) const
    {
    	return ptr->next;
    }	// end getNextNode
    I'm getting the same error on the first line of each of the above functions:

    Code:
    error: expected constructor, destructor, or type conversion before '*' token
    I've written constructors and destructors for the templated List class, so I'm not sure why only these three functions are giving me problems. The majority of my code for this project was copied out of the textbook, as per the assignment, so I'm not sure what the problem is. All of the other member functions seem to compile just fine.

    Any help would be greatly appreciated!
  • Laharl
    Recognized Expert Contributor
    • Sep 2007
    • 849

    #2
    Try moving the * to right after ListNode. So, ListNode* List<T>::getHea d(), rather than ListNode *List<T>::getHe ad(). The second one implies that the class is called *List<T> and the function returns a ListNode. The first tells the compiler that the class is called List<T> and the function returns a ListNode pointer.

    Comment

    • edyam
      New Member
      • Dec 2007
      • 8

      #3
      Hmm... Thanks for the suggestion, but it didn't seem to make a difference. Any other ideas?

      Thanks again!

      Comment

      • Ganon11
        Recognized Expert Specialist
        • Oct 2006
        • 3651

        #4
        Originally posted by Laharl
        Try moving the * to right after ListNode. So, ListNode* List<T>::getHea d(), rather than ListNode *List<T>::getHe ad(). The second one implies that the class is called *List<T> and the function returns a ListNode. The first tells the compiler that the class is called List<T> and the function returns a ListNode pointer.
        Laharl, actually, the whitespace here is a matter of preference - especially since classnames cannot start with the * character (else every time you said int *x, you would get an error).

        I expect that, since ListNode is itself a template struct, you need to treat it as a template in your return type:

        [CODE=cpp]ListNode<T>* List<T>::blahbl ahblah()[/CODE]

        Comment

        • edyam
          New Member
          • Dec 2007
          • 8

          #5
          Originally posted by Ganon11
          I expect that, since ListNode is itself a template struct, you need to treat it as a template in your return type:

          [CODE=cpp]ListNode<T>* List<T>::blahbl ahblah()[/CODE]
          Thanks, Ganon, but all that does is produce the following error...

          error: expected constructor, destructor, or type conversion before '<' token

          Thanks again!

          Comment

          • tavianator
            New Member
            • Dec 2006
            • 38

            #6
            Actually, ListNode is a nontemplate, nested struct. Your function should return a List<T>::ListNo de*. So

            Code:
            template <typename T>
            List<T>::ListNode* List<T>::foo();
            when declaring member functions inside classes, however, the List<T>:: is unnecessary.

            Comment

            • edyam
              New Member
              • Dec 2007
              • 8

              #7
              Originally posted by tavianator
              Actually, ListNode is a nontemplate, nested struct. Your function should return a List<T>::ListNo de*. So

              Code:
              template <typename T>
              List<T>::ListNode* List<T>::foo();
              when declaring member functions inside classes, however, the List<T>:: is unnecessary.
              That makes a lot of sense, tavianator, but I'm still getting the same error. Thanks anyway.

              Comment

              • edyam
                New Member
                • Dec 2007
                • 8

                #8
                I tried commenting out the three functions that were giving me errors, but that just caused me to get the following error on the first line of every member function:

                error: expected initializer before '<' token

                Any ideas/suggestions? Thanks in advance!

                Comment

                • Ganon11
                  Recognized Expert Specialist
                  • Oct 2006
                  • 3651

                  #9
                  Wait, I just remembered;

                  Are you defining these functions in the same file as your class? Template functions have to be defined in the same place they are declared (i.e. in the .h file).

                  Comment

                  • tavianator
                    New Member
                    • Dec 2006
                    • 38

                    #10
                    Actually, List<T>::ListNo de is a dependent name, so typename is required. Declare the functions like this:

                    Code:
                    template <typename T>
                    typename List<T>::ListNode* List<T>::find()
                    etc.

                    Comment

                    • edyam
                      New Member
                      • Dec 2007
                      • 8

                      #11
                      Re: Ganon

                      Adding 'typename' before the function results in the following error:
                      error: expected nested-name-specifier before 'List'

                      Re: tavianator

                      They're in two seperate files, but I've included

                      #include "ListTemplate.c pp"

                      at the bottom of ListTemplate.h, as per my professor's instructions for the project. This should be equivalent to having them in the same file, correct?

                      Comment

                      • tavianator
                        New Member
                        • Dec 2006
                        • 38

                        #12
                        I'm pretty sure you switched "re: Ganon" and "re: tavianator".

                        Anyway, the following code compiles fine with g++ 4.2.2. Some old compilers handle typename incorrectly, and that may be why the error persisted when you put typename List<T>::ListNo de *List<T>::find( ). Make sure you write it that way in all cases.

                        Code:
                        template <typename T>
                        class List
                        {
                          public:
                            
                            List();  // constructor
                            List(const List<T>& aList);// copy constructor
                            virtual ~List();  // destructor
                            
                            // overloaded assignment operator
                            List<T> & operator=(const List<T>& rhs);
                            
                            // member functions
                            virtual bool isEmpty() const;
                            virtual int getLength() const;
                            virtual void insert(int index, const T& newItem);
                            virtual void remove(int index);
                            virtual void retrieve(int index, T& dataItem) const;
                            virtual void removeAll();
                            
                          private: 
                          
                            struct ListNode
                            {
                              T item;
                              ListNode *next;
                            }; // end ListNode
                            
                            int size;
                            ListNode *head;
                            ListNode *find(int index) const;
                            void copyListNodes(List<T> origList);
                            
                          protected:
                          
                            void setSize(int newSize);
                            ListNode *getHead() const;
                            void setHead(ListNode *ptr) const;
                            T getNodeItem(ListNode *ptr) const;
                            ListNode *getNextNode(ListNode *ptr) const;
                            
                        } ;// end List
                        
                        template <typename T>
                        typename List<T>::ListNode *List<T>::find(int index) const
                        {
                          if ( (index < 1) || (index > getLength()) )
                          {
                            return 0;
                          }
                          
                          else
                          {
                            ListNode *cur = head;
                            
                            for (int skip = 1; skip < index; ++skip)
                            {
                              cur = cur->next;
                            } // end for
                            
                            return cur;
                          } // end if 
                        } // end find
                        
                        template <typename T>
                        typename List<T>::ListNode *List<T>::getHead() const
                        {
                          return head;
                        
                        } // end getHead
                        
                        template <typename T>
                        typename List<T>::ListNode *List<T>::getNextNode(ListNode *ptr) const
                        {
                          return ptr->next;
                        } // end getNextNode

                        Comment

                        • Ganon11
                          Recognized Expert Specialist
                          • Oct 2006
                          • 3651

                          #13
                          Originally posted by edyam
                          Re: tavianator

                          They're in two seperate files, but I've included

                          #include "ListTemplate.c pp"

                          at the bottom of ListTemplate.h, as per my professor's instructions for the project. This should be equivalent to having them in the same file, correct?
                          Yeah, this should have been Re:Ganon, but I figured it out XD

                          No, this is not the same. #include "ListTemplate.c pp" just means your program knows about the existence of the .cpp file and will look there for the function definitions. You need to define template functions in the same file i.e. in ListTemplate.h. You can still have the other functions in ListTemplate.cp p.

                          Comment

                          • edyam
                            New Member
                            • Dec 2007
                            • 8

                            #14
                            Sorry about the mixup! lol. Both of you have been extremely helpful. Using both of your suggestions, I'm no longer getting the original error messages, but the whole project still wont compile correctly. I intend to work on it some more later this evening, and I'll be sure to let you know about any new error messages I may get.

                            Thanks again for all your help.

                            Comment

                            Working...