More Effective C++ | An auto_ptr Implementation Back to Recommended Reading Continue to Books' Index An auto_ptr Implementation Items 9, 10, 26, 31 and 32 attest to the remarkable utility of the auto_ptr template. Unfortunately, few compilers currently ship with a "correct" implementation.1 Items 9 and 28 sketch how you might write one yourself, but it's nice to have more than a sketch when embarking on real-world projects. Below are two presentations of an implementation for auto_ptr. The first presentation documents the class interface and implements all the member functions outside the class definition. The second implements each member function within the class definition. Stylistically, the second presentation is inferior to the first, because it fails to separate the class interface from its implementation. However, auto_ptr yields simple classes, and the second presentation brings that out much more clearly than does the first. Here is auto_ptr with its interface documented: template class auto_ptr { public: explicit auto_ptr(T *p = 0); // see Item 5 for a // description of "explicit" template // copy constructor member auto_ptr(auto_ptr& rhs); // template (see Item 28): // initialize a new auto_ptr // with any compatible // auto_ptr ~auto_ptr(); template // assignment operator auto_ptr& // member template (see operator=(auto_ptr& rhs); // Item 28): assign from any // compatible auto_ptr T& operator*() const; // see Item 28 T* operator->() const; // see Item 28 T* get() const; // return value of current // dumb pointer T* release(); // relinquish ownership of // current dumb pointer and // return its value void reset(T *p = 0); // delete owned pointer; // assume ownership of p private: T *pointee; template // make all auto_ptr classes friend class auto_ptr; // friends of one another }; template inline auto_ptr::auto_ptr(T *p) : pointee(p) {} template inline auto_ptr::auto_ptr(auto_ptr& rhs) : pointee(rhs.release()) {} template inline auto_ptr::~auto_ptr() { delete pointee; } template template inline auto_ptr& auto_ptr::operator=(auto_ptr& rhs) { if (this != &rhs) reset(rhs.release()); return *this; } template inline T& auto_ptr::operator*() const { return *pointee; } template inline T* auto_ptr::operator->() const { return pointee; } template inline T* auto_ptr::get() const { return pointee; } template inline T* auto_ptr::release() { T *oldPointee = pointee; pointee = 0; return oldPointee; } template inline void auto_ptr::reset(T *p) { if (pointee != p) { delete pointee; pointee = p; } } Here is auto_ptr with all the functions defined in the class definition. As you can see, there's no brain surgery going on here: template class auto_ptr { public: explicit auto_ptr(T *p = 0): pointee(p) {} template auto_ptr(auto_ptr& rhs): pointee(rhs.release()) {} ~auto_ptr() { delete pointee; } template auto_ptr& operator=(auto_ptr& rhs) { if (this != &rhs) reset(rhs.release()); return *this; } T& operator*() const { return *pointee; } T* operator->() const { return pointee; } T* get() const { return pointee; } T* release() { T *oldPointee = pointee; pointee = 0; return oldPointee; } void reset(T *p = 0) { if (pointee != p) { delete pointee; pointee = p; } } private: T *pointee; template friend class auto_ptr; }; If your compilers don't yet support explicit, you may safely #define it out of existence: #define explicit This won't make auto_ptr any less functional, but it will render it slightly less safe. For details, see Item 5. If your compilers lack support for member templates, you can use the non-template auto_ptr copy constructor and assignment operator described in Item 28. This will make your auto_ptrs less convenient to use, but there is, alas, no way to approximate the behavior of member templates. If member templates (or other language features, for that matter) are important to you, let your compiler vendors know. The more customers ask for new language features, the sooner vendors will implement them. Back to Recommended Reading Continue to Books' Index 1 This is primarily because the specification for auto_ptr as for years been a moving target. The final specification was adopted only in November 1997. For details, consult the auto_ptr information at this book's WWW Site. Note that the auto_ptr described here omits a few details present in the official version, such as the fact that auto_ptr is in the std namespace (see Item 35) and that its member functions promise not to throw exceptions. Return