//Author: Jose M. Vidal
//
//A list class with iterators.
//It implements a small subset of the functionality found in
//the STL list container. 

#include<iostream>

using namespace std;

template<class T>
class List {
  
  class Node {
  public:
    T element;
    Node * next;
    Node() : next(0) {};
    Node(const T & e, Node * n = 0): element(e), next(n){};
    ~Node(){}
  };
  
  Node * header;
public:
  class Iterator {
    Node * iheader;
    Node * current;
  public:
    Iterator() : iheader(0), current(0) {};
    Iterator(Node * h, Node * c) : iheader(h), current(c) {};
    ~Iterator(){};
    void operator++() { current = current->next;};
    void operator++(int) {operator++();};
    T & operator*() {
      return current->element;}
    bool operator!=(const Iterator & i){
      return current != i.current;}
    bool operator==(const Iterator & i){
      return current == i.current;}
  };
  
  
  List() {
    header = new Node;};
  ~List() {
     MakeEmpty(); delete header;}
  bool IsEmpty(){return header->next == 0 };
  void MakeEmpty(){
    Node * nextNode;
    for (Node * c = header->next; c != 0; c = nextNode){
      nextNode = c->next;
      delete c;
    }
  };
  void add(T x){
    Node * n= new Node(x,header->next);
    header->next = n;
  }
  
  friend ostream & operator<<(ostream & os, const List<T> & l){
    Node * nextNode;
    for (Node * c = l.header->next; c != 0; c = nextNode){
      os << c->element << " ";
      nextNode = c->next;
    }
    return os;
  }
  Iterator begin(){
    return Iterator(header, header->next);
  };
  Iterator end(){
    return Iterator(header, 0);
  };
};

//This is a main that uses the List
// notice how the List can be used just like an STL list.
//
#include<iostream>
#include<string>
#include"List.h"
using namespace std;

int main(){

	List<int> l;
	l.add(2); l.add(3); l.add(4); l.add(5); l.add(6); l.add(7);
	cout << l;

	List<int>::Iterator i;
	cout << endl << "Iter" << endl;
	i = l.begin();
	for (i = l.begin(); i != l.end(); ++i){
		cout << *i << endl;
	}

	cout << "string" << endl;
	List<string> s;
	s.add("one"); s.add("two"); s.add("three"); s.add("four"); s.add("five");
	for (List<string>::Iterator si = s.begin(); si != s.end(); ++si)
		cout << *si << endl;

	return 0;
}