
Hi, (not sure if it was discussed before) I've found Boost smart pointers inflexible in the sense that they operate only on pointers. It would be a good idea to generalize their interface to handle just about anything that requires special care when destroying. HANDLE (on Windows), FILE*, file descriptors (on Unix), third-party API handles, etc. come to mind. I wrote a very simple class (see attachments), scoped_handle, which encapsulates the resource (whatever it is) and its disposing (whatever that means). The techniques used are similar to those used in implementation of boost::shared_ptr. The example file shows how the class can be used to guard resources allocated by operator new, fopen, open, etc. Is it possible to achieve the same results with the existing Boost libraries? If not, is there any interest in developing this kind of class? -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ // // Copyright (C) 2004 Maciej Sobczak // http://www.msobczak.com/ // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // #ifndef SCOPED_HANDLER_H_INCLUDED #define SCOPED_HANDLER_H_INCLUDED template <typename Resource> class disposer_base { public: virtual ~disposer_base() {} virtual void dispose(Resource) = 0; }; template <typename Resource, typename Deleter> class disposer_impl : public disposer_base<Resource> { public: disposer_impl(Deleter d) : d_(d) {} void dispose(Resource r) { d_(r); } private: Deleter d_; }; template <typename Resource> void simpleDeleter(Resource r) { delete r; } template <typename Resource> void arrayDeleter(Resource r) { delete [] r; } // requirements: // Resource and Deleter are copy-constructible and do not throw while copying // For Resource r and Deleter d, d(r) is a valid expression that doesn't throw template <typename Resource> class scoped_handle { public: scoped_handle(Resource r) : r_(r) { initDeleter(simpleDeleter<Resource>); } template <typename Deleter> scoped_handle(Resource r, Deleter d) : r_(r) { initDeleter(d); } ~scoped_handle() { disp_->dispose(r_); delete disp_; } Resource get() const { return r_; } private: scoped_handle(const scoped_handle &); scoped_handle & operator=(const scoped_handle &); template <typename Deleter> void initDeleter(Deleter d) { try { disp_ = new disposer_impl<Resource, Deleter>(d); } catch (...) { d(r_); throw; } } disposer_base<Resource> *disp_; Resource r_; }; #endif // SCOPED_HANDLER_H_INCLUDED #include "scoped_handle.h" #include <iostream> #include <functional> // this is for Unix only #include <fcntl.h> #include <unistd.h> using namespace std; class A { public: A() { cout << "A()\n"; } ~A() { cout << "~A()\n"; } }; void specialDeleter(A *p) { cout << "special deleter: "; delete p; } void anotherSpecialDeleter(A *p, int i) { cout << "another special deleter (" << i << "): "; delete p; } int main() { { scoped_handle<A*> h1(new A); scoped_handle<A*> h2(new A, specialDeleter); scoped_handle<A*> h3(new A, bind2nd(ptr_fun(anotherSpecialDeleter), 7)); // resources are released in the reverse order } { scoped_handle<FILE*> h4(fopen("test.txt", "w"), fclose); // ... } { // this is for Unix only scoped_handle<int> h5(open("test.txt", O_RDONLY), close); // ... } // etc. }