/* * $Header: /home/dscott/nasty/memory/autohndl.h,v 1.1 2001/11/06 21:48:50 dscott Exp $ * $NoKeywords: $ */ #ifndef AUTOHANDLE_H_ #define AUTOHANDLE_H_ 1 template<class H> struct handle_traits { static H null_value() { return 0; } static void dispose(H) throw(); static H clone(const H& h); }; // default auto_handle base class: // copy ctor is disabled template<class H, class T> class base_handle { public: base_handle() {} static void dispose(H h) throw() { T::dispose(h); } static H copy(H h) throw() { return h; } // place-holder static void swap(base_handle&) throw() {} private: base_handle(base_handle&); base_handle& operator=( base_handle&); }; // helper for returning // auto_handles by value template<class H> struct auto_handle_ref { explicit auto_handle_ref(H h) : handle_(h) {} H handle_; }; // auto_handle template<class H, class T = handle_traits<H>, class B = base_handle<H, T> > class auto_handle : private B { public: // 20.4.5.1 construct/copy/destroy explicit auto_handle( const H& h = T::null_value()) throw() : handle_(h) {} auto_handle(auto_handle& that) throw() : B(that), handle_(B::copy(that.handle_)) {} ~auto_handle() throw() { B::dispose(handle_); } // 20.4.5.2 members H get() const throw() { return handle_; } // release ownership H release() throw() { H h(handle_); handle_ = T::null_value(); return h; } void reset(const H& handle) throw() { if (handle_ != handle) { T::dispose(handle_); handle_ = handle; } } // 20.4.5.3 conversions // implicit ctor, clients may write // auto_handle<some_class> h = func() // where func returns auto_handle by // value auto_handle( const auto_handle_ref<H>& r) throw() : handle_(r.handle_) {} // other operators auto_handle& operator=( const auto_handle_ref<H>& r) { auto_handle tmp(r); swap(tmp); return *this; } auto_handle& operator=( auto_handle& rhs) { auto_handle tmp(rhs); swap(tmp); return *this; } operator auto_handle_ref<H>() { return auto_handle_ref<H>(release()); } bool operator !() const { return handle_ == T::null_value(); } void swap(auto_handle& that) throw() { B::swap(that); std::swap(handle_, that.handle_); } private: H handle_; }; // auto_handle template<class H, class T = handle_traits<H> > class cloner { public: cloner() {} cloner(const cloner&) {} static void dispose(H h) throw() { T::dispose(h); } static H copy(H h) { return T::clone(h); } }; #endif // AUTOHANDLE_H_ 1