Listing 7: Herb Sutters stack class first of three presented in his book, Exceptional C++
#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