Thread: Struggling with making circular linked list: compilation error from friend function?

  1. #1
    Registered User
    Join Date
    Jun 2014
    Location
    Tampa, Florida, United States
    Posts
    28

    Struggling with making circular linked list: compilation error from friend function?

    I've been getting the following error while trying to display my circular linked list and I have no idea how to fix the problem:

    prog.cpp:33:18: error: template-id 'operator<< <>' for 'std:: ostream& operator<<(std:: ostream&, const List<int>&)' does not match any template declaration
    friend ostream& operator << <>(ostream&, const List<T>&);



    here is my code:
    Code:
     
    
    #include <iostream>
    
    
    using namespace std; 
    
    
    
    
    template <class T>
    class List{
    
    
    private:
        class Node {
            public:
            T data;
            Node *next;
        };
    public:
    
    
        List();
        List(const List &);
        ~List();
    
    
        int getSize() const;
    
    
        bool isEmpty() const;
        bool insert(const T&, const int &);
        bool remove(const int &);
    
    
        T runJosephusAlgorithm();
    
    
        const List& operator=(const List&);
    
    
        void display(ostream&) const;
        
        friend ostream& operator << <>(ostream&, const List<T>&);
    
    
    private:
        Node *first; // pointer to the first element of the linked list
    
    
    
    
    
    
    };
    
    
    template<class T>
    List<T>::List()
    {
        first = NULL; 
    }
    
    
    
    
    template <class T>               
    List<T>::List(const List & Original_list)          // copy constructor creates copy of original list in body
    {
        
        Node *newNodeptr = NULL; 
        first  = Original_list.head; //original pointer
        
        do
        {
            newNodeptr = new Node;                              // do while 
            newNodeptr -> data = first ->data; 
            newNodeptr = newNodeptr ->next; 
            first = first ->next; 
            
        }while(first ->next!= Original_list.head);
        
    }
    
    
    
    
    
    
    template <class T>
    
    
    List<T>::~List()                                         
    {
       
    }
    
    
    template<class T> 
    bool List<T>::insert(const T&, const int & count)
    {
        int n = 1; 
        Node *currPtr; 
        Node *lastPtr; 
        Node *newNode; 
        
        newNode = new Node; 
        
        if (count == 1) 
        {
            newNode->next = first;
            first = newNode;
        }
        else
        {
            lastPtr = first; 
            currPtr = first; 
            
            while((currPtr !=NULL)&& (n < count))
            {
                n++;
                lastPtr = currPtr; 
                currPtr = currPtr ->next; 
            }
            lastPtr ->next = newNode; 
            currPtr = currPtr->next; 
        }
        
        
    }
    
    
    
    
    
    
    template <class T>
    void List<T>::display(ostream &out) const
    {
        Node *current = first;
        while (current != NULL) {
            out << current->data << endl;
            current = current->next;
        }
        
    }
    template <class T> 
    ostream & operator<<(ostream & o, const List<T> &output_elements)
    {
       o << output_elements.data; 
       return o; 
    }
    
    
    
    
    int main()
    {
        
        List<int> cll_1; 
        cll_1.insert(12,1);
        cll_1.insert(24,2);
        
        
        
    }

  2. #2
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Try moving the template for ostream & operator<< to before display. I didn't get a compile error from that, but did get an error because insert is supposed to return a boolean, but it doesn't return anything. The insert and copy templates compile, but they won't work. If the list is circular, then none of the node->next pointers will equal NULL. The last node's next pointer points to the first node, which may be itself if there is only one node. As mentioned in your prior thread, it would make more sense for the list class to have a pointer to the last node (Node *last) if you plan to add an append (push_back) function. You could have both a first and a last pointer, but the pointer for the first node = last->next if last is not NULL, so it can be created easily if the pointer to the last node is maintained by the class.
    Last edited by rcgldr; 09-10-2015 at 11:47 PM.

  3. #3
    Tweaking master Aslaville's Avatar
    Join Date
    Sep 2012
    Location
    Rogueport
    Posts
    528
    This code works for me as is with Visual Studio 2013, I didn't check with other versions.

    It also works with clang 3.5 though I get a link error with the destructor.

    This code doesn't work with gcc though. Moving the templete for ostream & operator<< before display doesn't cut it either.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,403
    Quote Originally Posted by Aslaville
    Moving the templete for ostream & operator<< before display doesn't cut it either.
    Instead of moving, forward declare:
    Code:
    template<class T>
    class List;
    
    template<class T>
    ostream& operator << (ostream&, const List<T>&);
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    To clarify my previous post, the only error I got using VS2005 (also have VS2015, but didn't try it yet), was insert is supposed to return a boolean, but it doesn't return anything.

    As far as the actual code, it seems that insert should be checking for first == NULL, and I don't see where it sets the last nodes next pointer to the first node (since it's supposed to be a circular list).
    Last edited by rcgldr; 09-11-2015 at 01:22 AM.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Don't use VS2005! It's old and outdated!
    If you're going to try someone else's code, do it using an up-to-date compiler!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Jun 2014
    Location
    Tampa, Florida, United States
    Posts
    28
    I couldn't figure out how to do the copy constructor, so I decided to work on the insert function so I can be able to insert a node into the list, and be able to output the list and go from there. Everything seems to compile now, however I can't figure out how to output the linked list. The header file was given to me by my professor and I just don't understand how to print out the list with the code she has given me, it's incredibly frustrating. Here's what I made so far:


    For the header file:
    Code:
     
    
    #include <iostream>
    
    
    using namespace std;
    
    
    
    
    template <class T>
    class List {
    
    
    private:
    	class Node {
    	public:
    		T data;
    		Node *next;
    	};
    public:
    
    
    	List();
    	List(const List &);
    	~List();
    
    
    	int getSize() const;
    
    
    	bool isEmpty() const;
    	bool insert(const T&, const int &);
    	bool remove(const int &);
    
    
    	T runJosephusAlgorithm();
    
    
    	const List& operator=(const List&);
    
    
    	void display(ostream&) const;
    
    
    	friend ostream& operator << <>(ostream&, const List<T>&);
    
    
    private:
    	Node *first; // pointer to the first element of the linked list
    
    
    
    
    
    
    };
    
    
    template<class T>
    List<T>::List()
    {
    	first = NULL;
    }
    
    
    
    
    template <class T>
    List<T>::List(const List & Original_list)          // copy constructor creates copy of original list in body
    {
    	
    }
    
    
    
    
    
    
    template <class T>
    
    
    List<T>::~List()
    {
    
    
    }
    
    
    template<class T>
    bool List<T>::insert(const T& data, const int & count)
    {
    	int n = 1; 
    	Node *lastPtr;
    	Node *currPtr; 
    	Node *newNode = new Node; 
    	
    	if (count == 1)
    	{
    		
    		newNode->next = first;
    		first = newNode;
    		return true; 
    	}
    	
    	if (count > 1 && count != 0)
    	{
    	
    		currPtr = first;
    		lastPtr = first;
    
    
    		while ((currPtr != NULL) && (n < count)) 
    		{
    			
    			n++;
    			lastPtr = currPtr;
    			currPtr = currPtr->next;
    		}
    		lastPtr->next = newNode;
    		newNode->next = currPtr;
    
    
    		return true;
    
    
    	}
    	else
    		return false; 
    
    
    
    
    }
    
    
    
    
    
    
    template <class T>
    void List<T>::display(ostream &out) const
    {
    	Node *current = first;
    	while (current != NULL) {
    		out << current->data << endl;
    		current = current->next;
    	}
    
    
    }
    template <class T>
    ostream & operator<<(ostream & o, const List<T> &output_elements)
    {
    	o << output_elements.data;
    	return o;
    }

    and the main function:
    Code:
    #include<iostream>
    #include"circularlist.h"
    
    
    
    
    
    
    
    
    int main()
    {
    	List<int> cl_1; 
    	cl_1.insert(12, 1);
    
    
    	cl_1.display();      // No idea how to print this out????
    	
    }

  8. #8
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    For the insert function parameters, you might want to consider the count for nodes starting at zero instead of one. So insert(data, 0) would create a new node for the start of a list, similar to push_front(). Also you might want to consider keeping track of the number of nodes in list, similar to std::list::size().

    Looking at the insert function, I don't see where it handles first == NULL. Since this is a circular list, then the last node of the list has a next pointer == first, not NULL.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 09-09-2015, 11:07 PM
  2. Still struggling with sorting a singly linked list
    By jou00jou in forum C Programming
    Replies: 3
    Last Post: 03-13-2008, 11:07 AM
  3. circular linked->list help
    By The Brain in forum C++ Programming
    Replies: 8
    Last Post: 10-21-2004, 11:12 AM
  4. Circular linked list
    By campermama in forum C++ Programming
    Replies: 7
    Last Post: 06-15-2004, 11:53 AM
  5. Circular Linked list ....
    By yescha in forum C Programming
    Replies: 1
    Last Post: 11-17-2001, 03:41 AM