#include <stdlib.h>
#include <iostream.h>

template <class T>
class TQueue {

  friend ostream& operator << (ostream&, TQueue<T>&);

public:
  TQueue()
  {
    front = back = 0;
  }
  ~TQueue();

  T get();
  void put(const T&);

  int is_empty()
  {
    return((!front) ? 1 : 0);
  }

private:

  class TQueueItem {
    // friend ostream& operator << (ostream&, TQueueItem<T>&);

  public:
    TQueueItem(T value): item(value), next(0)
    {
    }

    T item;
    TQueueItem *next;
  };

  TQueueItem *front, *back;
};

/*
template <class T>
ostream& operator << (ostream &os, TQueueItem<T> &qi)
{
  os << qi.item;
  return os;
}
*/

template <class T>
ostream& operator << (ostream &os, TQueue<T> &q)
{
  os << "< ";
  TQueue<T> :: TQueueItem *p;
  for(p = q.front; p; p = p -> next)
    os << p -> item << " ";

  os << " >" << endl;
  return os;
}

template <class T>
TQueue<T> :: ~TQueue()
{
  while(!is_empty()) (void)get();
}

template <class T>
void TQueue<T> :: put(const T &value)
{
  TQueueItem *pt = new TQueueItem(value);
  if(is_empty()) {
    front = back = pt;
  }
  else {
    back -> next = pt;
    back = pt;
  }
}

template <class T>
T TQueue<T> :: get()
{
  if(is_empty()) {
    cout << "Trying to Get from the empty queue !\n";
    exit(-1);
  }

  TQueueItem *pt = front;
  front = front -> next;

  T value = pt -> item;
  delete pt;

  return value;
}


int main() {

  TQueue<int> i_q;
  for(int i = 0; i < 10; ++i)
  {
    i_q.put(i); i_q.put(10 * i);
  }
  cout << i_q;

  while(!(i_q.is_empty())) {
    cout << i_q.get() << endl;
  }

  cout << i_q;


  return 0;
}