#include <iostream>
using namespace std;

class Element
{
      int liczba;
      public :
             Element(int a = 1):liczba(a){};
             int Liczba()const{return liczba;};
};
      
template<class Typ>      
class Stack
{
      public:
             Stack(int = 10);         //domyslnie stos 10 elementowy
             ~Stack(){delete [] stackPtr;ilosc--;}//destruktor, zmniejszamy liczbe stworzonych stosow
             int push(const Typ& );
             int pop(Typ&);
             int isEmpty() const {return top == -1;};//sprawdzamy czy stos jest pusty
             int isFull() const {return top == size -1;};//czy jest pelny
             Typ value(){return stackPtr[top];};         //metoda do wyswietlania wartosci ze stosu
             int ile(){return ilosc;};
      private:
              int size;
              int top;
              Typ * stackPtr;
              static int ilosc;        //zmienna statyczna - ilosc stworzonych stosow
              
};

template<class Typ>   
int Stack<Typ>::ilosc=0;              //zmiennej statycznej nadajemy poczatkowa wartosc
//#############################################
template<class Typ>  
Stack<Typ>::Stack(int s)
{ 
     size = s > 0 && s < 1000 ? s : 10;//jesli podana wartosc jest w granicach od 0 do 1000 to tworzymy taki stos, w przeciwnym razie tworzymy stos 10 elementowy
     top = -1;                         //
     stackPtr = new Typ[size];         //tworzymy dynamicznie nowa tablice danego rozmiaru
     ilosc++;                          //zwiekszamy ilosc stworzonych stosow
}
//#############################################
template<class Typ>  
int Stack<Typ>::push(const Typ& item)
{
     if(!isFull())              //dopoki stos nie jest pelny
     { 
        stackPtr[++top] = item; //wkladamy na stos
        return 1;               
     }
    return 0;
}
//#############################################
template<class Typ>  
int Stack<Typ>::pop(Typ& popValue)
{
    if(!isEmpty())                //dopoki stos nie jest pusty
    { 
       popValue = stackPtr[top--]; //sciagamy ze stosu
       return 1;                   //jesli prawda zwracamy 1
    }
    return 0;                      //jesli sie nie uda zwracamy 0
}

int main(int argc, char *argv[])
{
    Stack<float> floatStack(20);    //tworzymy nowy stos dla zmiennych typu float
    int i=1;                       //zmienna pomocnicza tylko dla obliczen
    float b;                       //zmienna do ktorej wkladamy element sciagniety ze stosu
    cout<<"Wkladanie na stos: \n";
    while(!floatStack.isFull())    //wypelniamy stos
    {
        floatStack.push(i*1.1);    //wladamy na stos
        cout<<floatStack.value()<<"\t";//wyswietlenie wartosci na gorze stosu
        i++;                       //
    }

    i=1;                               
    Stack<Element*> ElementStack(5);//nowy stos wskaznikow na Element
    cout<<"\nWkladanie na stos: \n";
    while(!ElementStack.isFull())   //wypelniamy stos dopoki jest miejsce
    {
        Element* w=new Element(i+10);//tworzymy nowy element do ktorego wskanik wsadzamy na stos
        ElementStack.push(w);        //wkladamy na stos
        cout<<ElementStack.value()<<"("<<w->Liczba()<<")\t";//wyswietlamy adres i w nawiasie wartosc
        i++;
    }
    
    cout<<"\nSciaganie ze stosu: \n";    
    while(!floatStack.isEmpty())   //oprozniamy stos
    {
        floatStack.pop(b);         //sciagamy ze stosu
        cout<<b<<"\t";             //wyswietlamy sciagnieta wartosc
    }
    
    cout<<"\nSciaganie ze stosu: \n";
    while(!ElementStack.isEmpty())   //znowu oprozniamy stos
    {
        Element* w;                  //pomocnicza zmienna dla sciaganych wartosci
        cout<<ElementStack.value()<<"(";//wyswietlamy adres
        ElementStack.pop(w);            //sciagamy ze stosu
        cout<<w->Liczba()<<")\t";       //wyswietla wartosc spod wskaznika
        delete w;                       //oczywiscie usuwamy dynamicznie stworzony obiekt
        i++;
    }
    //Za pomoca zmiennej statycznej mozemy tylko powidziec ile jest stosow danego typu! a nie wszystkich stosow!
    cout<<endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}
