I'm trying to make a custom set of header files to use a generic List and use operator<< to make it print into a ostream object There are a couple of errors which I cannot resolve.
I'm trying to make a generic List class using a generic Node class. The generic List should be printed using the operator<< . However I'm getting a lot of errors.
#include <iostream>
using std::cout;
using std::ostream;
class List;
template<class T>
class Node
{
    friend class List<Node>;
    private:
    T data_;
    Node *next_;
    public:
    Node(T data);
    T get_data();
};
template<typename T>
Node<T>::Node(T data)
{
    data_ = data;
    next_ = 0;
}
template<typename T>
T Node<T>::get_data()
{
     return data_;
}
template<typename T>
class Node;
template<typename T>
class List
{
    template<typename T>
    friend ostream& operator<<(ostream& o , const List<T> head);
    private:
    Node<T> *start_;
    bool is_empty();
    public:
    List();
    ~List();
    void insert(T data);
    void remove();  
};
template<typename T>
bool List<T>::is_empty()
{
    if(start_ == 0)
        return true;        
    return false;
}
template<typename T>
List<T>::List()
{
    start_ = 0;
}
template<typename T>
List<T>::~List()
{
    if( !is_empty())
    {
        Node<T> *current = start_;
        Node<T> *temp;
        while(current != 0)
        {
            temp = current;
            current = current->next_;
            delete temp;
        }
    }
}
template<typename T>
void List<T>::insert(T data)
{
    if(is_empty())
    {
        Node<T> *temp = new Node<T>(data);
        start_ = temp;
    }
    else
    {
        Node<T> *temp = start_;
        while(temp->next_ != 0)
        {
            temp = temp->next_;
        }
        temp->next_ = new Node<T>(data);
    }
}
template<typename T>
void List<T>::remove()
{
    if(start_->next_ == 0)
    {
        Node<T> *temp = start_->next_;
        start_->next_ = 0;
        delete temp; 
    }
    else if(!is_empty())
    {
        Node<T> *stay = start_;
        Node<T> *remove = stay->next_;
        while(remove->next_ != 0)
        {
            stay = remove;
            remove = remove->next_;
        }
        stay->next_ = 0;
        delete remove;
    }
}
 // Experimental Stuff out here
template<typename T>
ostream& operator<<(ostream& o , const List<T> *head)
{
    Node<T> *temp = head->start_;
    if(!is_empty<T>())
    {
        while(temp->next_ != 0)
        {
            o << temp.get_data() << "\t";
            o << "\n";
            temp = temp->next_;
        }
    }
    return o;
}
//  End of Experimental Stuff
 
    