#ifndef STACK_H
#define STACK_H
#include <cassert>
#include <algorithm> // for swap
#include <cstdlib> // for size_t
#define STACK_HAS_TOP
template <class T>
class Stack
{
public:
Stack();
~Stack();
Stack( const Stack& );
Stack& operator=( const Stack& );
std::size_t Size() const;
void Push( const T& );
const T& Top() const; // if empty, throws exception.
void Pop(); // if empty, throws exception.
// Just checks that the internal representation
// is consistent, ie not destroyed.
bool Consistent() const;
private:
std::size_t vsize_;
T* v_; // ptr to a memory area big enough for 'vsize_' Ts
std::size_t vused_; // # of T's actually in use
T* NewCopy( const T* src,
std::size_t srcsize,
std::size_t destsize );
};
template<class T>
Stack<T>::Stack():
vsize_( 10 ), // initial allocation size
v_( new T[vsize_] ),
vused_( 0 ) // Nothing used yet
{}
template<class T>
Stack<T>::~Stack()
{
delete [] v_;
}
template<class T>
Stack<T>::Stack( const Stack<T>& other ) :
vsize_( other.vsize_ ),
v_( NewCopy( other.v_,
other.vused_,
other.vsize_ ) ),
vused_( other.vused_ )
{}
template<class T>
Stack<T>&
Stack<T>::operator=( const Stack<T>& other )
{
if( this != &other ) {
T* v_new = NewCopy( other.v_,
other.vused_,
other.vsize_ );
delete [] v_; // this can't throw
v_ = v_new;
vsize_ = other.vsize_;
vused_ = other.vused_;
}
return *this;
}
template<class T>
std::size_t Stack<T>::Size() const
{
return vused_;
}
template<class T>
void Stack<T>::Push( const T& t )
{
if( vused_ == vsize_ ) { // grow if necessary by some
// grow factor
size_t vsize_new = vsize_*2 + 1;
T* v_new = NewCopy( v_, vsize_, vsize_new );
delete [] v_; // this can't throw
v_ = v_new; // take ownership
vsize_ = vsize_new;
}
v_[vused_] = t;
++vused_;
}
template<class T>
const T& Stack<T>::Top() const
{
if( vused_ == 0 ) {
throw "empty stack";
}
return v_[vused_-1];
}
template<class T>
void Stack<T>::Pop()
{
if( vused_ == 0 ) {
throw "empty stack";
}
--vused_;
}
template<class T>
bool Stack<T>::Consistent() const
{
// Weak check.
return vused_ <= vsize_ and v_ != NULL;
}
template<class T>
T* Stack<T>::NewCopy( const T* src,
std::size_t srcsize,
std::size_t destsize )
{
assert( destsize >= srcsize );
T* dest = new T[destsize];
try {
copy( src, src+srcsize, dest );
}
catch(...) {
delete [] dest;
throw;
}
return dest;
}
#endif // STACK_H
End of Listing