I’m following an example in Accelerated C++ and writing a simple Handle class that will act as a smart pointer. This uses the virtual ctor idiom using a virtual clone() function. So far so good. But what to do when I want to use my Handle for classes that I don’t control that don’t provide clone()?
The method suggested in the book is to create a global clone function and use template specialization (something I’m seeing for the first time) so that if clone() is called with a particular argument, one can write code to handle that case.
My question is: This means that I have to write a clone() version for every type of class that I envision my user can use Handle with. This seems quite hard! Is there a more elegant and/or simple way to solve this issue? How is it possible that things like auto_ptr or boost::shared_ptr are able to provide this functionality without the tedious clone() definitions?
For completeness, here’s my Handle class implementation:
template <class T> class Handle
{
public:
Handle() : p(0) {}
Handle(T* t) : p(t) {}
Handle( const Handle& s ) :p(0) { if (s.p) p = s.p->clone(); }
const Handle& operator=( const Handle& );
~Handle() { delete p; }
operator bool() { return p; }
T& operator*() { if (p) return *p; else throw std::runtime_error("Handle not bound"); }
T* operator->() { if (p) return p; else throw std::runtime_error("Handle not bound"); }
private:
T* p;
};
Thanks!
The solution to this problem is to simply not write
Handles for these kinds of classes. No. Really.auto_ptr(deprecated as of C++11) never needs to clone the underlying object, becauseauto_ptrnever copies the object. Anauto_ptronly ever has one copy of the object, and when theauto_ptris copied, control of the object is transfered — that object is not copied.unique_ptrnever needs to clone the underlying object, because there is only ever oneunique_ptrthat owns the object.unique_ptris noncopyable, and is only movable.shared_ptrnever needs to clone because it also only ever controls one copy of the object. Copying theshared_ptronly increments the reference count, and that single object is destroyed when the reference count is zero.In general, if there’s no way to deep copy the resource your class is controlling, then you should just make the class noncopyable. If clients need to pass references to your class around, they can place the class in an
auto_ptr,unique_ptr, orshared_ptrthemselves.