Listing 2

#include <cassert>
#include <typeinfo>

  const bool deletable = true;

  // used to uniquely identify the return type of new operations
  template<typename T>
  class new_ptr {
  public:
    new_ptr(T* x) : m(x) { };
    T* m;
  };
  // used to cast from a raw pointer (generated from a new operation) to
  // a new_ptr
  template<typename T>
  inline new_ptr<T> new_cast(T* x) {
    return new_ptr<T>(x);
  };
  // this pointer type does not allow deletion of the resource
  template<typename T, bool deleteable_B = false>
  class ptr  {
  public:
    ptr() : m(NULL) { };
    ptr(const ptr& x) : m(x.m) { };
    ptr(T* x) : m(x) { };
    ptr(const ptr<T, deletable>& x) : m(x.raw_pointer()) { };
    T* operator->() const {
      return m;
    }
    T& operator*() {
      return m;
    }
    const T& operator*() const {
      return m;
    }
    bool operator==(ptr x) const {
      return m == x.m;
    }
    bool operator!=(ptr x) const {
      return m != x.m;
    }
    void Release() {
      m = NULL;
    }
    static ptr null() {
      return ptr();
    }
    void operator=(const ptr<T, true>& x) {
      m = x.raw_pointer();
    }
  private:
    T* m;
  };
  // this pointer type allows manual deletion of the referenced resource but
  // does not automatically destroy!
  // This differs from the ptr template by introducing a Delete() function
  template<typename T>
  class ptr<T, true> {
  public:
    ptr() : m(NULL) { };
    ptr(const ptr& x) : m(x.m) { };
    explicit ptr(const new_ptr<T>& x) : m(x.m) { };
    T& operator*() {
      return m;
    }
    const T& operator*() const {
      return m;
    }
    void Delete() {
      assert(m != NULL);
      delete m;
      assert((m = NULL) == NULL);
    }
    void Release() {
      m = NULL;
    }
    T* operator->() const {
      return m;
    }
    T* raw_pointer() const {
      return m;
    }
    static ptr null() {
      return ptr();
    }
    operator ptr<T, false>() const {
      return m;
    }
    void operator=(new_ptr<T> x) {
      m = x.m;
    }
  private:
    T* m;
  };