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; };