Overloading << operator in C++ when using templates in linked list program

余生颓废 提交于 2019-12-02 12:13:19

问题


I'm trying to implement a linked list. But I'm receiving an error when I try overloading the << operator. This is my program:

#include<iostream>
#include<stdlib.h>
using namespace std;

template<class T> class List;

template<class T>
class Node
{
    T data;
    Node* next;
    public:
        Node(T val)
        {
            data = val;
            next = NULL;
        }
        Node(T val, Node* link)
        {
            data = val;
            next = link;
        }
        friend class List<T>;
        friend ostream& operator<<(ostream& out, List<T>* li);
};

template<class T>
class List
{
    Node<T>* first;
    Node<T>* last;
    public:
        friend ostream& operator<< (ostream& out, List<T>* li)
        {
            if(li->first)
                out<<"Empty.\n";
            else
            {
                out<<"Displaying: \n";
                Node<T>* p = li->first;
                while(p)
                {
                    out<<p->data;
                    p = p->next;
                }
            }

            return out;
        }
        List()
        {
            first = last = NULL;
        }
        List(T val)
        {
            Node<T>* l = new Node<T>(val);
            first = last = l;
        }
        void insertHead(T val)
        {
            if(first)
            {
                Node<T>* p = new Node<T>(val,first);
                first = p;
            }
            else
                first = last = new Node<T>(val);
        }
        void insertTail(T val)
        {
            if(first)
            {

                last->next = new Node<T>(val);
                last = last->next;
            }
            else
                first = last = new Node<T>(val);
        }
        void insertAt(T val, int pos)
        {
            //check if list is empty.
            if(first==NULL)
                first = new Node<T>(val);
            else
            if(pos==1)
                insertHead(val);
            else
            {
                Node<T>* curr = first;
                int i = 1;
                // iterate till position is reached.
                while( i<pos )
                {
                    curr=curr->next;
                    i++;
                }
                //create new node.
                Node<T>* p = new Node<T>(val,curr->next);
                //link new node to previous node.
                curr->next = p;
            }
        }
        void concatenate(List<T>* m)
        {
            //m is concatenated to end of *this.
            if(first)
            {
                last->next = m->first;
                last = m->last;
            }
            else
            {
                first = m->first;
                last = m->last;
            }
            m->first = m->last = 0;
        }
        void delVal(int pos)
        {
            //if position is first, delete first node.
            if( pos == 1 )
            {
                Node<T>* p = first;
                first = first->next;
                if(first==0)
                    last=0;

                free(p);
            }
            //otherwise, iterate till correct position and delete the node.
            else
            {
                int i = 1;
                Node<T>* curr = first;
                while( i<pos )
                {
                    curr = curr->next;
                    i++;
                }
                Node<T>* p = curr->next;
                curr->next = p->next;
                if(curr->next==0)
                    last = curr;
                free(p);
            }
        }

        void searchVal(T val)
        {
            Node<T>* curr = first;
            int i = 0;
            cout<<"Search: ";
            while( curr )
            {
                if( curr->data==val )
                {
                    cout<<val<<" found at position "<<i<<endl;
                    break;
                }
                else
                {
                     curr=curr->next;
                     i++;
                }
            }
            cout<<endl;
        }
        void recDisplay(Node<T>* curr)
        {

            if(curr!=0)
            {
                cout<<curr->data<<endl;
                recDisplay(curr->next);
            }

        }

        void Display()
        {
            cout<<"Displaying: \n";
            recDisplay(first);
        }
        void Reverse()
        {
            Node<T>* curr = first;
            Node<T>* prev = 0;
            while( curr )
            {
                Node<T>* r = prev;
                prev = curr;
                curr = curr->next;
                prev->next = r;
            }
            first = prev;
        }
        ~List()
        {
            Node<T>* p = first;
            cout<<"Deleting:"<<endl;
            while(first!=0)
            {
                free(first);
                first = p->next;
                p = first;
            }
        }
};



int main()
{
    List<int>*  l = new List<int>();
    l->insertHead(5);
    l->insertTail(6);
    l->insertTail(7);
    cout<<l;

}

When i execute this code, the compiler gives me the following errors:

warning: friend declaration 'std::ostream& operator<<(std::ostream&, List*)' declares a non-template function [-Wnon-template-friend]

note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)

Please help.


回答1:


Since they take a class template argument, your friends need to be function templates, or specializations of function templates:

// function template friend
template <typename T2>
friend ostream& operator<<(ostream& out, const List<T2>& li);

Note that one would usually overload this operator to take a reference, not a pointer, as in the example above.

The drawback is that this is probably not restrictive enough: ostream& operator<<(ostream& out, const List<Widget>& li) would be a friend of List<int>. Since this is not usually the desired behaviour, you can provide a template specialization, which would restrict friendship to the same T as that with which the class is instantiated:

// function template, declared outside of the class:
template <typename T>
ostream& operator<<(ostream& out, const List<T2>& li);

// function template specialization, declared inside the class:
friend ostream& operator<< <>(ostream& out, const List<T>& li);


来源:https://stackoverflow.com/questions/18814928/overloading-operator-in-c-when-using-templates-in-linked-list-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!