#ifndef REFSTACK_H
#define REFSTACK_H
#include <iostream>
template <typename T> class stack;
template <typename T>
std::ostream &operator<<( std::ostream &os, const stack<T> &s);
template <typename T>
class stack
{
friend std::ostream &operator<< <>( std::ostream &os, const stack &s);
public:
stack() : cap(ibs), sp(0), v(new T[ibs]), cnt(new int(1)) { }
stack( const stack &other) { attach(other); }
~stack() { detach(); }
stack& operator=( const stack &other);
void push( const T &t);
const T &pop() { return v[--sp]; }
bool empty() const { return 0 == sp; }
void *test_address() const { return v; }
private:
int cap;
int sp;
double *v;
int *cnt;
static const int ibs = 8;
void detach();
void attach( const stack &other);
void copy( const T *ov);
void grow();
};
template <typename T>
void stack<T>::detach()
{
// Nem thread-safe!
if ( 0 == --*cnt )
{
delete cnt;
delete [] v;
}
}
template <typename T>
void stack<T>::attach( const stack &other)
{
// Nem thread-safe!
cap = other.cap;
sp = other.sp;
v = other.v;
cnt = other.cnt;
++*cnt;
}
template <typename T>
stack<T>& stack<T>::operator=( const stack &other)
{
if ( this != &other ) // x = x
{
detach();
attach(other);
}
return *this;
}
template <typename T>
void stack<T>::push( const T &t)
{
// Nem thread-safe!
if ( 1 < *cnt )
{
--*cnt;
if ( cap == sp )
cap *= 2;
copy(v);
cnt = new int(1);
}
if ( cap == sp )
grow();
v[sp++] = t;
}
template <typename T>
void stack<T>::copy( const T *oldv)
{
v = new T[cap];
for ( int i = 0 ; i < sp; ++i)
v[i] = oldv[i];
}
template <typename T>
void stack<T>::grow()
{
T* oldv = v;
cap *= 2;
copy(oldv);
delete [] oldv;
}
template <typename T>
std::ostream &operator<<( std::ostream &os, const stack<T> &s)
{
os << "[ ";
for ( int i = 0; i < s.sp-1; ++i )
os << s.v[i] << ", ";
if ( s.sp > 0 )
os << s.v[s.sp-1];
os << " ]";
return os;
}
#endif /* REFSTACK_H */