Listing 7: Herb Sutter’s 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 —