Class Templates - linkedlist.cpp - A generic Link List

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

template<typename T>
class Node
{
	T  data_;
	Node* next_;
	Node(const Node&);   // disable copy ctor
public:
	Node();
	Node(T d, Node* n);
	const T& data() const;
	T& data();
	Node* next() const;
	Node*& next();
};

template<typename T> Node<T>::Node()
: data_(), next_(0)
{}

template<typename T> Node<T>::Node(T d, Node* n)
: data_(d), next_(n)
{}

template<typename T> const T& Node<T>::data() const
{
	return data_;
}

template<typename T> T& Node<T>::data()
{
	return data_;
}

template<typename T> Node<T>* Node<T>::next() const
{
	return next_;
}

template<typename T> Node<T>*& Node<T>::next()
{
	return next_;
}

template<typename T> ostream& operator<<(ostream& out, const Node<T>& N)
{
	out << N.data();
	return out;
}

template<typename T> class List
{
	Node<T>* top_;
public:
	List();
	~List();
	void push(T object);
	T pop();
	const Node<T>* const top() const;
	bool remove(T object);
	const Node<T>* find(T object) const;
};

template<typename T> ostream& operator<<(ostream& out, const List<T>& L) 
{
	const Node<T>* ptr = L.top();
	while (ptr) {
		out << (*ptr) << endl;
		ptr = ptr -> next();
	}
	return out;
}

template<typename T> List<T>::List()
: top_(0)
{}

template<typename T> List<T>::~List()
{
	Node<T>* ptr = top_;
	while (ptr) {
		top_ = top_->next();
		delete ptr;
		ptr = top_;
	}
}

template<typename T> void List<T>::push(T object)
{
	Node<T>* ptr = new Node<T>(object, top_);
	top_ = ptr;
}

template<typename T> const Node<T>* const List<T>::top() const
{
	return top_;
}

template<typename T> T List<T>::pop()
{
	Node<T>* ptr = top_;
	top_ = top_ -> next();
	T data = ptr->data();
	delete ptr;
	return data;
}

template<typename T> const Node<T>* List<T>::find(T object) const
{
	const Node<T>* ptr = top();
	while (ptr) {
		if (ptr->data() == object) {
			return ptr;
		}
		ptr = ptr->next();
	}
	return 0;
}

template<typename T> bool List<T>::remove(T object)
{
	if (!find(object)) {
		cerr << object << " not found\n";
		return false;
	}
	Node<T>* ptr2current = top_;
	Node<T>* ptr2previous = top_;
	if (top_->data() == object) {
		top_ = top_ -> next();
		delete ptr2current;
		return true;
	}
	while (ptr2current) {
		ptr2current = ptr2current->next();
		if (ptr2current->data() == object) {
			ptr2previous->next() = ptr2current->next();
			delete ptr2current;
			return true;
		}
		ptr2previous = ptr2current;
	}
	return false;
}

const string suit_name[4] = {"clubs","diamonds","hearts","spades"};
const string pips_name[13] = {"two","three","four","five","six","seven","eight",
"nine","ten","jack","queen","king","ace"};

class card
{
protected:
	int pips, suit;
public:
	card();
	bool operator==(const card& c) const;
	friend ostream& operator<<(ostream&, const card&);
};

card::card()
: pips(rand()%13), suit(rand()%4)
{}

bool card::operator==(const card& c) const
{
	return pips==c.pips && suit == c.suit;
}

ostream& operator<<(ostream& out, const card& C)
{
	out << pips_name[C.pips] << " of " << suit_name[C.suit];
	return out;
}


int main()
{
	Node<int> Nint(5,0);
	cout << Nint << endl;

	card C1;
	card C2;
	card C3;
	card C4;
	card C5;
	List<card> Lcard;
	Lcard.push(C1);
	Lcard.push(C2);
	Lcard.push(C3);
	Lcard.push(C4);
	Lcard.push(C5);
	cout << Lcard << endl;

	List<int> Lint;
	Lint.push(2);
	Lint.push(4);
	Lint.push(6);
	Lint.push(8);
	Lint.push(10);

	cout << Lint << endl;
	return 0;
}

/********************** output ********************************
5
two of clubs
ace of hearts
nine of clubs
five of clubs
four of spades

10
8
6
4
2
*********************/