#include <iostream>
using namespace std;

class Process
  {
   public:
   unsigned Proc,Time;
   Process():Proc(0),Time(0) {}
   Process(unsigned Proc,unsigned Time):Proc(Proc),Time(Time) {}
  };
  
ostream &operator<<(ostream &s,const Process &P)
  {
   return s<<'('<<P.Proc<<':'<<P.Time<<')';
  }

template <class Typ> class Kolejka
  {
   private:
   class Element
     {
      private:
      Element *Nastepny;
      Typ Dane;
      public:
      Element(Typ Dane):Dane(Dane),Nastepny(0) {}
/*
void Free(Typ &Dane,Element *&Nastepny)
  {
   Nastepny=this->Nastepny;
   Dane=this->Dane;
   delete this;
  }
*/
      friend class Kolejka;
     }*Pierwszy,*Ostatni;
   void Kopiuj(const Kolejka &K);
   public:
   class Pusta{};
   void Czysc();
   ostream &Drukuj(ostream &s)const;
   Kolejka():Pierwszy(0),Ostatni(0) {}
   Kolejka(const Kolejka &K):Pierwszy(0),Ostatni(0) { Kopiuj(K); }
   ~Kolejka() { Czysc(); }
   Kolejka &operator=(const Kolejka &K) { Czysc(); Kopiuj(K); return *this; }
   Kolejka &operator<<(Typ Dane);
   Kolejka &operator>>(Typ &Dane);
   Kolejka &operator<<(const Kolejka &K) { Kopiuj(K); return *this; }
   void operator>>(Kolejka &K) { K.Kopiuj(*this); Czysc(); }
   operator bool()const { return Pierwszy; }
  };

template <class Typ> void Kolejka<Typ>::Kopiuj(const Kolejka<Typ> &K)
  {
   for(Element *tmp=K.Pierwszy;tmp;tmp=tmp->Nastepny)
     {
      operator<<(tmp->Dane);
     }
  }

template <class Typ> void Kolejka<Typ>::Czysc()
  {
   while(Pierwszy)
     {
      Element *tmp=Pierwszy;
      Pierwszy=Pierwszy->Nastepny;
      delete[] tmp;
     }
  }

template <class Typ> ostream &Kolejka<Typ>::Drukuj(ostream &s)const
  {
   s<<'{';
   bool F=true;
   for(Kolejka::Element *tmp=Pierwszy;tmp;tmp=tmp->Nastepny)
     {
      if(F) F=false; else s<<',';
      s<<tmp->Dane;
     }
   return s<<'}';
  }

template <class Typ> Kolejka<Typ> &Kolejka<Typ>::operator<<(Typ Dane)
  {
   Ostatni=(Ostatni?Ostatni->Nastepny:Pierwszy)=new Element(Dane);
   return *this;
  }

template <class Typ> Kolejka<Typ> &Kolejka<Typ>::operator>>(Typ &Dane)
  {
   if(!Pierwszy) throw Pusta();

// Pierwszy->Free(Dane,Pierwszy);
   Element *tmp=Pierwszy;
   Pierwszy=Pierwszy->Nastepny;
   Dane=tmp->Dane;
   delete tmp;
   
   if(!Pierwszy) Ostatni=0;
   return *this;
  }

template <class Typ> ostream &operator<<(ostream &s,const Kolejka<Typ> &K)
  {
   return K.Drukuj(s);
  }
  
#define Prt(var) #var<<'='<<var<<';'

int main()
  {
   Kolejka<double> K,L;
   K<<3<<5<<7;
   cout<<Prt(K)<<endl;
   L=K;
   cout<<Prt(L)<<endl;
   if(K)
     {
      double x,y,z;
      K>>x>>y>>z;
      cout<<"x="<<x<<"; y="<<y<<"; z="<<z<<';'<<endl;
      
      if(!K)
        {
         cout<<"Proba wyciagania z pustej"<<endl;
         try
           {
            double k;
            K>>k;
           }
         catch(Kolejka<double>::Pusta)
           {
            cout<<"Powstal blad"<<endl;
           }
         cout<<"Ale idzemy dalej"<<endl;
        }
        
     }
   cout<<Prt(K)<<endl;
   K<<L<<L;
   cout<<Prt(K)<<endl;
   cout<<Prt(L)<<endl;
   K>>L;
   cout<<Prt(K)<<endl;
   cout<<Prt(L)<<endl;

   cout<<"--------------------"<<endl;

   if(true)
     {
      Kolejka<Process> K,L;
      K<<Process(1,300)<<Process(2,200)<<Process(3,100);
      cout<<Prt(K)<<endl;
      L=K;
      cout<<Prt(L)<<endl;
      if(K)
        {
         Process x,y,z;
         K>>x>>y>>z;
         cout<<"x="<<x<<"; y="<<y<<"; z="<<z<<';'<<endl;

         if(!K)
           {
            cout<<"Proba wyciagania z pustej"<<endl;
            try
              {
               Process k;
               K>>k;
              }
            catch(Kolejka<Process>::Pusta)
              {
               cout<<"Powstal blad"<<endl;
              }
            cout<<"Ale idzemy dalej"<<endl;
           }

        }
      cout<<Prt(K)<<endl;
      K<<L<<L;
      cout<<Prt(K)<<endl;
      cout<<Prt(L)<<endl;
      K>>L;
      cout<<Prt(K)<<endl;
      cout<<Prt(L)<<endl;
     }
     
   cin.get();
   return 0;
  }

