// Implement a generic stack class using templates.


#include <iostream.h>
#include <string.h>


template<class T>
class stack {

    public:

    stack(size_t size = 10);
    ~stack();
    stack(const stack &s);
    stack & operator=(const stack &s);
    void push(const T &value);
    T pop();
#ifdef SEPARATE
    friend ostream & operator<<(ostream &os, const stack &s);
#else
    friend ostream & operator<<(ostream &os, const stack &s) {
        for (T *ptr = s.top ; ptr >= s.base ; ptr--) {
            os << *ptr << endl;
        }
        return os;
    }
#endif

    private:

    T *base;
    T *top;
    size_t size;

};


template<class T>
stack<T>::stack(size_t size) {
    this->base = new T[size];
    this->top = this->base - 1;
    this->size = size;
}


template<class T>
stack<T>::~stack() {
    delete[] this->base;
}


template<class T>
stack<T>::stack(const stack<T> &s) {
    delete[] this->base;
    this->base = new T[s.size];
    int elements = (s.top - s.base) + 1;
    memcpy((void *)this->base, (void *)s.base, elements*sizeof(T));
    this->top = this->base + (elements - 1);
}


template<class T>
stack<T> & stack<T>::operator=(const stack<T> &s) {
    delete[] this->base;
    this->base = new T[s.size];
    int elements = (s.top - s.base) + 1;
    memcpy((void *)this->base, (void *)s.base, elements*sizeof(T));
    this->top = this->base + (elements - 1);
    return *this;
}


template<class T>
void stack<T>::push(const T &value) {
    *(++(this->top)) = value;
}


template<class T>
T stack<T>::pop() {
    return *((this->top)--);
}


#ifdef SEPARATE
template<class T>
ostream & stack<T>::operator<<(ostream &os, const stack<T> &s) {
    for (T *ptr = s.top ; ptr >= s.base ; ptr--) {
        os << *ptr << endl;
    }
    return os;
}
#endif
