
Maciej Sobczak <prog@msobczak.com> wrote:
It depends on how you count this "simplicity". For 99% cases I can think of (in fact, for 100% - the 1% margin is for my humble assumption that one cannot think of everything ;) ), the smart handle would be needed to provide exception safety to raw handles which manage some external resources (files, sockets, DB connections, sessions, statements, transactions, processes, etc.) and which automate their cleanup. All these resources take much more time (usually orderS of magnitude) to allocate and cleanup than a single new.
I've yet to see a realistic example where such resource is significantly cheaper than operator new. And even if this is realistic, it would be easy to extend the machinery to use some tuned allocation strategy, like recycling memory pool, so that the allocation by new comes down to just few CPU cycles.
In other words, I do not consider this solution to be an overkill. Moreover, it is quite cheap and can buy some interesting features - for example, you can change the deleter at run-time (the basic Strategy pattern).
That does make sence. []
Interesting, but I would add is_null() predicate to the traits. This is so that the Handle does not need to define its own operator== and operator!= (but you can always delegate the generic traits to these operators).
Agreed.
template< class Handle , class Pfn , Pfn close , class Tag , class Traits = scoped_handle_traits<Handle> > class scoped_handle : private boost::noncopyable [...]
{ public: typedef Tag tag_type; [...]
Would you please explain what is the need for Tag or tag_type?
The example is win32 handles. Being different entities they may have the same HANDLE type and are closed using CloseHandle(). I needed to make overloads on scoped_handle<> type, so as scoped_handle<> typedef for such handles would be the same type I had to add Tag template parameter. -- Maxim Yegorushkin