Listing 1 Class templates for CheckedPtr and CheckedClassPtr

//checkptr.h listing 1
// copyright 1995 Robert Mashlan

#ifndef _CHECKPTR_H
#define _CHECKPTR_H

#include <stddef.h>
#include <except.h>
#include <cstring.h>

class xCheckedPtr: public xmsg
{
   public:
      xCheckedPtr( const string& why ) : xmsg(why) {}
};

class xnullptr: public xCheckedPtr {
   public:
      xnullptr() : xCheckedPtr("dereferenced null pointer") {}
      void raise() { throw *this; }
};

class xoutofrange: public xCheckedPtr {
   public:
      xoutofrange() : xCheckedPtr("pointer out of range") {}
      void raise() { throw *this; }
};

class xnotsamebase: public xCheckedPtr {
   public:
      xnotsamebase()
         : xCheckedPtr("comparison between two pointers not of the same base")
         {}
      void raise() { throw *this; }
};

template<class T>

class CheckedPtr {
   public:
      // default constructor
      CheckedPtr(T *p = 0, size_t limit=1, T* base = 0 )
         : p(p), base(base?base:p), limit(limit)
         {
            if(p>this->base+limit||p<this->base)
               xoutofrange().raise();
         }
      // copy constructor
      CheckedPtr( const CheckedPtr<T>& orig )
         : p(orig.p), base(orig.base), limit(orig.limit)
         {}

      // access to base and limit
      void SetBaseAndLimit( T* base, size_t limit )
         {
            if(!base)
               base = p;
            if(!limit)
               limit = 1;
            this->base=base;
            this->limit=limit;
            if( p && (p<base || base+limit<p) )
               xoutofrange().raise();
         }

      // conversion operator
      operator T*() const
         { return p; }

      // reference operators
      T& operator*() const
         { return operator[](0); }
      T& operator[]( ptrdiff_t i ) const
         {
            if(!p) // null pointer?
              xnullptr().raise();
            // check for out of range reference
            if( p+i<base || base+limit <= p+i )
              xoutofrange().raise();
            return p[i];
         }
      // assignment operators
      CheckedPtr<T>& operator=( const CheckedPtr<T>& cp )
         { p = cp.p; base=cp.base; limit=cp.limit; return *this; }
      CheckedPtr<T>& operator=( T* p )
         { this->p = base = p; limit = 1; return *this; }
      CheckedPtr<T>& operator+=( ptrdiff_t n )
         {
            if(!p)
               xnullptr().raise();
            if( p+n < base || base + limit < p+n )
               xoutofrange().raise();
            p += n;
            return *this;
         }
      CheckedPtr<T>& operator-=( ptrdiff_t n )
         { return operator+=(-n); }
      // additive operators
      CheckedPtr<T> operator+( ptrdiff_t n ) const
         { return CheckedPtr<T>(*this).operator+=(n); }
      CheckedPtr<T> operator-( ptrdiff_t n ) const
         { return CheckedPtr<T>(*this).operator-=(n); }
      ptrdiff_t operator-( const CheckedPtr<T>& cp ) const
         {
            if(base!=cp.base)
               xnotsamebase().raise();
            return p-cp.p;
         }
      ptrdiff_t operator-( CheckedPtr<T>& cp ) const
         { return operator-((const CheckedPtr<T>)cp); }
      ptrdiff_t operator-( T *p ) const
         {
            if( p<base || base+limit<p )
               xnotsamebase().raise();
            return this->p-p;
         }
      friend ptrdiff_t operator-( T* p, CheckedPtr<T>& cp );

      // increment and decrement
      CheckedPtr<T>& operator++(int)
         { return operator+=(1); }
      CheckedPtr<T> operator++()

         {
            CheckedPtr<T> r(*this);
            operator++(0);
            return r;
         }
      CheckedPtr<T>& operator--(int)
         { return operator-=(1); }
      CheckedPtr<T> operator--()
         {
            CheckedPtr<T> r(*this);
            operator--(0);
            return r;
         }

      // logical negation
      bool operator!() const
         { return !p; }

      // equality operators
      bool operator==( const CheckedPtr<T>& cp ) const
         { return p == cp.p; }
      bool operator==( T* p ) const
         { return this->p == p; }
      bool operator != ( const CheckedPtr<T>& cp ) const
         { return p != cp.p; }
      bool operator!=( T* p ) const
         { return this->p != p; }

      // relational operators
      bool operator<( const CheckedPtr<T>& cp ) const
         { return operator-(cp) < 0; }
      bool operator<( T* p ) const
         { return operator-(p) < 0; }
      bool operator<=( const CheckedPtr<T>& cp ) const
         { return operator-(cp) <= 0; }
      bool operator<=( T* p ) const
         { return operator-(p) <= 0; }

      bool operator>( const CheckedPtr<T>& cp ) const
         { return operator-(cp) > 0; }
      boo1 operator>( T* p ) const
         { return operator-(p) > 0; }
      bool operator>=( const CheckedPtr<T>& cp ) const
         { return operator-(cp) >= 0; }
      bool operator>=( T* p ) const
         { return operator-(p) >= 0; }

   protected:
      T* p;          // pointer that this class represents
      T* base;       // base of the array that p is a member of
      size_t limit;  // number of elements in the array.
                  // 1 for non-array pointers
};

template<class T> inline
ptrdiff_t operator-( T* p, CheckedPtr<T>& cp )
{
   if( p < cp.base || cp.base+cp.limit < p )
      xnotsamebase().raise();
   return p-cp.p;
}

template<class T> inline
CheckedPtr<T> operator+( ptrdiff_t n, const CheckedPtr<T>& cp )
{
   return cp.operator+(n);
}

// non-member equality operators

template<class T> inline
bool operator==( T* p. const CheckedPtr<T>& cp )
{
   return cp.operator==(p);
}

template<class T> inline
bool operator!=( T* p, const CheckedPtr<T>& cp )
{
   return cp.operator!=(p);
}

// non-member relational operators

template<class T> inline
bool operator<( T* p, const CheckedPtr<T>& cp )
{
   return cp.operator>=(p);
}

template<class T> inline
bool operator<=( T* p, const CheckedPtr<T>& cp )
{
   return cp.operator>(p);
}

template<class T> inline
bool operator>( T* p, const CheckedPtr<T>& cp )
{
   return cp.operator<=(p);
}

template<class T> inline
bool operator>=( T* p, const CheckedPtr<T>& cp )
{
   return cp.operator<(p);
}

template<class T>
class CheckedClassPtr: public CheckedPtr<T> {
   public:
      CheckedClassPtr(T *p=0, size_t limit=1, T* base=0 )
         : CheckedPtr<T>(p, limit,base)
         {}
      CheckedClassPtr( const CheckedClassPtr<T>& orig )
         : CheckedPtr<T>(orig)
         {}

      // class memory access operator
      T* operator->() const { return &operator*(); }

      // assignment operators
      CheckedClassPtr<T>& operator=( const CheckedClassPtr<T>& cp )
         { CheckedPtr<T>::operator=(cp); return *this; }
      CheckedClassPtr<T>& operator+=( ptrdiff_t n )
         { CheckedPtr<T>::operator+=(n); return *this; }
      CheckedClassPtr<T>& operator-=( ptrdiff_t n )
         { CheckedPtr<T>::operator-=(n); return *this; }

      // additive operators
      CheckedClassPtr<T> operator+( ptrdiff_t n ) const
         { return CheckedClassPtr<T>(*this).operator+=(n); }
      CheckedClassPtr<T>operator-( ptrdiff_t n ) const
         { return CheckedClassPtr<T>(*this).operator-=(n); }

      // increment and decrement
      CheckedClassPtr<T>& operator++(int)
         { return operator+=(1); }
      CheckedClassPtr<T> operator++()
         { CheckedClassPtr<T> r(*this); operator++(0); return r; }
      CheckedClassPtr<T>& operator--(int)
         { operator-=(1); return *this; }
      CheckedClassPtr<T> operator--()
         { CheckedClassPtr<T> r(*this); operator--(0); return r; }
};

template<class T> inline
CheckedClassPtr<T> operator + ( ptrdiff_t n, const CheckedClassPtr<T>& p )
{
   return p.operator+(n);
}

#endif