auto_ptr
ImplementationItems 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.† 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 T>
class auto_ptr {
public:
explicit auto_ptr(T *p = 0); // see Item 5 for a
// description of "explicit"
template<class U> // copy constructor member
auto_ptr(auto_ptr<U>& rhs); // template (see Item 28):
// initialize a new auto_ptr
// with any compatible
// auto_ptr
~auto_ptr();
template<class U> // assignment operator
auto_ptr<T>& // member template (see
operator=(auto_ptr<U>& 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<class U> // make all auto_ptr classes
friend class auto_ptr<U>; // friends of one another
};
template<class T>
inline auto_ptr<T>::auto_ptr(T *p)
: pointee(p)
{}
template<class T>
template<class U>
inline auto_ptr<T>::auto_ptr(auto_ptr<U>& rhs)
: pointee(rhs.release())
{}
template<class T>
inline auto_ptr<T>::~auto_ptr()
{ delete pointee; }
template<class T>
template<class U>
inline auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<U>& rhs)
{
if (this != &rhs) reset(rhs.release());
return *this;
}
template<class T>
inline T& auto_ptr<T>::operator*() const
{ return *pointee; }
template<class T>
inline T* auto_ptr<T>::operator->() const
{ return pointee; }
template<class T>
inline T* auto_ptr<T>::get() const
{ return pointee; }
template<class T>
inline T* auto_ptr<T>::release()
{
T *oldPointee = pointee;
pointee = 0;
return oldPointee;
}
template<class T>
inline void auto_ptr<T>::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 T>
class auto_ptr {
public:
explicit auto_ptr(T *p = 0): pointee(p) {}
template<class U>
auto_ptr(auto_ptr<U>& rhs): pointee(rhs.release()) {}
~auto_ptr() { delete pointee; }
template<class U>
auto_ptr<T>& operator=(auto_ptr<U>& 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<class U> friend class auto_ptr<U>;
};
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_ptr
s 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.