
I've been lurking on this thread for awhile now, and as a person who is very familiar with the design and use of single-ownership smart pointer with custom-deleter capability, I figured it was time to throw my two cents in... I find custom deleters handy with single-ownership even when I'm not trying to move them out of scope. I usually use: const unique_ptr<MyClass, MyDeleter<A>> p(...); The const qualifier on the unique_ptr renders the unique_ptr to be practically the same thing as scoped_ptr. It will take a const_cast for this animal to transfer the ownership out of the scope. I've also found that sometimes I'll start with a same-scope use, but during refactoring, learn that I want to move the smart pointer creation into a factory function (for reuse in several places). When I do that, it is handy to not have to change smart pointer types (besides dropping the const qualifier if I used that). I've also found support for statefull deleters quite necessary (as opposed to just handling stateless deleters). The proposed code: template<class T, class D = boost::checked_deleter<T> > // first patch line class scoped_ptr { // ... public: ~scoped_ptr() { // ... deleter()(ptr); // second patch line, instead of boost::checked_delete } }; does not handle statefull deleters. If this community does decide to put a custom deleter into scoped_ptr (and I am ambivalent on that decision), then I strongly encourage the designers of this patch to mimic the custom deleter of unique_ptr. The latest specification of it can be found here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2914.pdf (search for "[unique.ptr]") And here is a more readable link in tutorial form which hits the highlights: http://home.roadrunner.com/~hinnant/unique_ptr03.html (and includes a C++03 emulation). The basic layout would look like: template<class T, class D = boost::checked_deleter<T> > // checked_deleter<T[]> should be partially specialized to handle arrays class scoped_ptr { typedef typename details::compute_pointer<T, D>::type pointer; tuple<pointer, D> ptr_; ... }; Until tuple is rewritten with the empty member optimization, you'll want to use compressed_pair<pointer, D> instead. The "compute_pointer" business defaults to T* unless D::pointer exists, in which case pointer is D::pointer. This supports putting this smart pointer in shared memory. Allocators, which are a common use case, often have this nested type, and sometimes, it is not a raw pointer. Storing the D as shown above will: 1. Optimize away the space for it when D is empty. 2. Support function pointer types. 3. Support non-empty (statefull) Ds. I also recommend supporting lvalue-reference D types. This is very handy when dealing with a stateful D that you don't want to move or copy (say because it is a data member of the enclosing class). Such support will probably come for free in C++0x, but requires a little extra work in C++03 to avoid the reference-to-reference situation. I also recommend deleter accessors which return *references* to the deleter: D& get_deleter(); const D& get_deleter() const; It is not uncommon to need access to the actual stored deleter (not a copy of it) during the lifetime of the smart pointer (I needed this just yesterday in code I was writing). This is used to change the state of the deleter which alters the behavior the deallocation process (e.g. do (or don't) destruct a certain field in the held object). And you'll want scoped_ptr constructors which accept a deleter (to initialize its state). And you'll want to disable the constructors which don't take a deleter when D is a pointer or reference type (lest it be null). scoped_ptr<A[]> could be a nice synonym for scoped_array<A> if checked_deleter is specialized for T[]. It is nothing more (or less) than a nice, easy to remember name for the array variant of the smart pointer. When you get done, you will have reinvented all of the const parts of unique_ptr (which has several years of refinement under its belt by now). I don't necessarily discourage that as it is a very educational exercise. -Howard