handle management with boost::shared_ptr<>
I would like to use boost::shared_ptr<> to encapsulate the lifetime management of a handle. My handle and it's creation/destruction functions are declared like this:
typedef const struct MYHANDLE__ FAR* MYHANDLE;
void CloseMyHandle( MYHANDLE );
MYHANDLE CreateMyHandle();
Ideally, I would like to use the boost::shared_ptr<>
like this to manage the handle:
boost::shared_ptr< void > my_handle( CreateMyHandle(), &CloseMyHandle );
Unfortunately, because the handle is declared as a const struct *
instead of the usual void *
, I get errors like this:
boost/smart_ptr/shared_ptr.hpp(199) : error C2440: 'initializing' : cannot convert from 'const MYHANDLE__ *' to 'void *'
I can use a functor to cast the void *
to a MYHANDLE
like this:
struct DeallocateMyHandle
{
void ope开发者_如何学Crator()( void* handle )
{
CloseMyHandle( ( MYHANDLE )handle );
};
};
boost::shared_ptr< void > my_handle( ( void* )CreateMyHandle(), DeallocateMyHandle() );
But, I'd rather have a method that doesn't involve the separate functor. Is there a way to do this just within the boost::shared_ptr<>
constructor that I'm not seeing? Or, am I stuck with the functor?
Thanks, PaulH
Why not use:
boost::shared_ptr< const MYHANDLE__ > my_handle( CreateMyHandle(), &CloseMyHandle );
PS. Note the use of double underscore is not allowed (it is reserved for the implementation).
See: Rules about identifers
If HANDLE is a public type, but the type it points to is not, there's a really easy way to write this:
template <typename T> struct unpointer { };
template <typename T> struct unpointer<T*> { typedef T type; };
boost::shared_ptr<typename unpointer<MYHANDLE>::type> my_handle(
CreateMyHandle(), &CloseMyHandle);
(If you're using a really old version of VC++ or gcc you probably have to omit the "typename" there.)
Of course this gets a bit verbose and tedious. If you're only got one handle type to deal with, you probably to write this:
typedef typename unpointer<MYHANDLE>::type MYHANDLEREF;
typedef boost::shared_ptr<MYHANDLEREF> my_shared_ptr;
If you've got all kinds of handles to wrap (and since it looks like you're doing Win32 API stuff, you probably do), create a template that wraps things up at whatever level you prefer (a class template that just generates the types, a handle_ptr<T>
that subclasses shared_ptr<unpointer<T>>
and adds the default deleted for you, a handle_ref<T>
that uses a shared_ptr
behind the scenes to fake being a MYHANDLE &
instead of faking being what MYHANDLE
is a pointer to, etc.)
Your shared_ptr
type needs to be this:
boost::shared_ptr< const MYHANDLE__ FAR>
That way when shared_ptr
makes a pointer out of it, it becomes:
const MYHANDLE__ FAR*
Which matches your MYHANDLE
type exactly:
#include <boost/shared_ptr.hpp>
struct MYHANDLE__ {};
typedef const MYHANDLE__* MYHANDLE;
void CloseMyHandle(MYHANDLE) {}
MYHANDLE CreateMyHandle(void) { return 0; }
int main()
{
typedef boost::shared_ptr<const MYHANDLE__> ptr_type;
ptr_type my_handle( CreateMyHandle(), &CloseMyHandle );
}
Note, I really doubt you need FAR
, that's from the 16-bit ages. It expands to either far
or nothing, depending on if you're compiling for 16-bit (hint: you aren't compiling to 16-bit. :) ). far
isn't even an extension anymore, as far as I know.
Also, like Martin said don't use double-underscores anywhere.
精彩评论