#include <iostream>
#include <math.h>

using namespace std;

template <class Typ> class Tablica
  {
   private:
   unsigned R;
   Typ *T;
   public:
   Tablica(unsigned Rozmiar=0); // uzycie: Tablica T(3),A;
   Tablica(const Tablica &Tb); // uzycie: przekazywanie i zwracanie przez wartosc. Tablica T(3),B(T),A=T;
   ~Tablica(); // uzycie: automatycznie;
   operator unsigned()const { return R; } // zwraca rozmiar; uzycie: Tablica T(3); if(T<4) ...
   unsigned operator ()()const { return R; } // zwraca rozmiar; uzycie: Tablica T(3); if(T()<4) ...
   void operator ()(unsigned Rozmiar); // zmienia rozmiar; uzycie: Tablica T(3); T(8);
   Typ &operator [](unsigned P) { return T[P]; } // uzycie: Tablica T(3); T[2]=5;
   const Typ &operator [](unsigned P)const { return T[P]; } // uzycie: const Tablica T(3); Typ x=T[0];
   Tablica &operator=(const Tablica &Tb); // uzycie: const Tablica T(3),A; A=T;
   Tablica &operator<<(Typ x); // dopisuje wartosc x do tablcy; uzycie: Tablica A; A<<1<<2<<3;
   Tablica &operator<<(const Tablica &Tb); // dopisuje cala tablice do tablcy; uzycie: Tablica A(2),B(3); A<<B;
  };

template <class Typ> Tablica<Typ>::Tablica(unsigned Rozmiar):R(Rozmiar),T(R?new Typ[R]:0)
  {
   //for(unsigned i=0;i<R;++i) T[i]=0;
   memset(T,0,R*sizeof(Typ));
  }

template <class Typ> Tablica<Typ>::Tablica(const Tablica<Typ> &Tb):R(Tb.R),T(R?new Typ[R]:0)
  {
   //for(unsigned i=0;i<R;++i) T[i]=Tb.T[i];
   memcpy(T,Tb.T,R*sizeof(Typ));
  }

template <class Typ> Tablica<Typ>::~Tablica()
  {
   if(R) delete[] T;
  }

template <class Typ> void Tablica<Typ>::operator ()(unsigned Rozmiar) // zmienia rozmiar;
  {
   Typ *N=Rozmiar?new Typ[Rozmiar]:0;
   if(R)
     {
      //unsigned Min=R<Rozmiar?R:Rozmiar;
      //for(unsigned i=0;i<Min;++i) N[i]=T[i];
      memcpy(N,T,(R<Rozmiar?R:Rozmiar)*sizeof(Typ));
      delete[] T;
     }
   if(Rozmiar>R)
     {
      //for(unsigned i=R;i<Rozmiar;++i) N[i]=0;
      memset(N+R,0,(Rozmiar-R)*sizeof(Typ));
     }
   T=N;
   R=Rozmiar;
  }

template <class Typ> Tablica<Typ> &Tablica<Typ>::operator =(const Tablica<Typ> &Tb) // To co destruktor potem to co konstruktor kopiujacy
  {
   if(R) delete[] T;
   R=Tb.R;
   T=R?new Typ[R]:0;
   //for(unsigned i=0;i<R;++i) T[i]=Tb.T[i];
   memcpy(T,Tb.T,R*sizeof(Typ));
   return *this;
  }
  
template <class Typ> Tablica<Typ> &Tablica<Typ>::operator <<(Typ x)
  {
   // Tablica<Typ> &t=*this; unsigned r=t; t(r+1); t[r]=x;
   // unsigned r=*this; (*this)(r+1); (*this)[r]=x;
   unsigned r=operator unsigned(); // uzywamy operator jako metode;
   operator ()(r+1); // uzywamy operator jako metode;
   operator [](r)=x; // uzywamy operator jako metode;
   return *this;
  }  

template <class Typ> Tablica<Typ> &Tablica<Typ>::operator<<(const Tablica<Typ> &Tb)
  {
   unsigned r=operator unsigned(); // uzywamy operator jako metode;
   operator ()(r+Tb); // uzywamy operator jako metode;
   //for(unsigned i=0;i<Tb;++i) T[i+r]=Tb.T[i];
   memcpy(T+r,Tb.T,Tb*sizeof(Typ));
   return *this;
  }

template <class Typ> ostream &operator <<(ostream &s,const Tablica<Typ> &T)// uzycie: Tablica<Typ> T(2); cout<<T<<endl;
  {
   s<<'{';
   for(unsigned i=0;i<T;++i)
     { 
      if(i) s<<',';
      s<<T[i];
     }
   return s<<'}';
  }

class Punkt
{
  private:
  public:
    double x1, y1;
    Punkt(double x1 = 0, double y1 = 0):x1(x1), y1(y1) {}
};

class Obiekt:public Punkt
{
  public:
        virtual ostream &Drukuj(ostream &s)const { return s<<"To jest Drukuj() dla Obiektu"; }
        Obiekt(double x1 = 0, double y1 = 0):Punkt(x1,y1) {}
};
ostream &operator<< (ostream &s, const Obiekt & X)
{
  return X.Drukuj(s);
}

class Prostokat:public Obiekt
{
        private:
          Punkt p2;
        public:
          Prostokat(double x1 = 0, double y1 = 0, double x2 = 0, double y2 = 0): Obiekt(x1,y1), p2(x2, y2) {}
        virtual ostream &Drukuj(ostream &s)const { return s<<"To jest Drukuj() dla Prostokata"; }
};

int main(void)
  {
    Tablica<Obiekt> T(1);
    Obiekt  Obkt;
   while(true)
     {
      cout<<"Polecenie: ";
      switch(cin.get())
        {
         case '!': return 0;
         case '\n': continue;
         case '+':
            switch(cin.get())
              {
               default:
                 cin.ignore(1024,'\n');
               case '\n':
                 cout<<"blad"<<endl<<endl;
               continue;
               case 'p':
               case 'P':
                double x1, y1, x2, y2;
                cin >> x1 >> y1 >> x2 >> y2;
/*
                unsigned P = T();
                T(P + 1);
                T[P + 1] = new Prostokat(x1, y1, x2, y2);
*/
                T[0] = new Prostokat(x1, y1, x2, y2);
                 cin.ignore(1024,'\n');
               break;
               case 'k':
               case 'K':
                 cout<<"Wprowadzamy Kolo"<<endl;
                 cin.ignore(1024,'\n');
               break;
               case 't':
               case 'T':
                 cout<<"Wprowadzamy tekst"<<endl;
                 cin.ignore(1024,'\n');
               break;
              }
         break;
         case '$':
           cout<<"Tu drukujemy"<<endl;     
           cin.ignore(1024,'\n');
         break;
         default:
           cin.ignore(1024,'\n');
           cout<<"blad"<<endl<<endl;
         break;
        }
     }
  }

