1

I'm implementing a singly linked list. Here's the node class

template <typename T> class node{

    friend class slist<T>;
    public:
        explicit node():data(0), next(NULL){}

    private:
        T data;
        node<T> *next;

};

And here's the list class.

template<typename T> class slist{
    public:
        slist():head(NULL){}


        bool empty(){
            return head == NULL;
        }

        void add_front(const T& data){
            if(head == NULL){
                node<T>* n = new node<T>();
                n->data = data;
                n->next = NULL;
                head = n;
                return;
            }
            node<T>* n = new node<T>();
            n->data = data;
            n->next = head;
            head = n;
        }

        void remove_front(){
            if(head == NULL) return;
            node<T>* old = head;
            head = old->next;
            delete old;
        }

        void print_list(){
            if(head == NULL) return;
            while(!empty()){
                std::cout<<head->data<<std::endl;
                head = head->next;
            }
        }

        ~slist(){

            while(!empty()) remove_front();

        }

    private:
        node<T>* head;
};

The implementation works perfectly fine if I declare the members in the node as public. However the moment I declare them private and make the slist a friend class, I get the following error.

In file included from src.cpp:3:
./slist.hpp:5:28: error: redefinition of 'slist' as different kind of symbol
template<typename T> class slist{
                           ^
./node.hpp:4:15: note: previous definition is here
        friend class slist;

I can obviously find other implementation of single linked list, but I'm trying to understand what's going wrong here. So please refrain from unsolicited advice as "google it". Thanks.

Jumper
  • 215
  • 3
  • 15
  • 1
    Your code doesn't match your error. Your error says `friend class slist;`. Your code says `friend class slist;`. Which is it? – T.C. Jun 24 '15 at 23:00
  • @TC do you want me to put up the calling client class. Since the error comes during compilation which involves a main program instantiating a list and adding a few members. – Jumper Jun 24 '15 at 23:05
  • 2
    What you need to do is supply a SMALL but COMPLETE sample of code that illustrates your problem. In particular, it is not clear what order the two templates appear in your source file, if they appear in different ones, etc. Anyway, look at http://stackoverflow.com/questions/8967521/c-class-template-with-template-class-friend-whats-really-going-on-here – Peter Jun 24 '15 at 23:14

2 Answers2

2

You need to forward declare the List class as a template class:

#include <iostream>

template<typename T> class List; //<< fwd decl

template<typename T> class Node {
    int i;
public:
    friend class List<T>; //<< usage same as you have now
    Node() : i(123) {}
    int value() { return i; }
};

template<typename T> class List { //<< definition
public:
    List(Node<T>* node) { node->i++; }
};

int main() {
    Node<int> node{};
    List<int> list{&node};
    std::cout << node.value() << "\n";
}

http://ideone.com/2RUWgj

kfsone
  • 23,617
  • 2
  • 42
  • 74
0

The friend class declaration needs it's own template parameter declaration without shadowing the enclosing classes template parameters:

template<typename U> class slist; // Forward declare slist

template <typename T> 
class node{

    template<typename U> // <<<<<
    friend class slist<U>;
                    // ^ <<<<<
    // ...
}; 
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190