views:

90

answers:

2

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 operator()( 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

+4  A: 

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

Martin York
What makes you think that MYHANDLE__ isn't an implementation name?
DeadMG
Because it starts with MY ( as in mine rather than my initials)
Martin York
Still looks like a double underscore to me. Any name with double underscores (or leading underscore followed by a capital letter) is reserved for the implementation.
David Thornley
using `MYHANDLE__` yields this error: `boost/smart_ptr/shared_ptr.hpp(199) : error C2440: 'initializing' : cannot convert from 'const MYHANDLE__ *' to 'MYHANDLE__ *'`
PaulH
@PaulH: What happens if you add const to the type in shared pointer? (as edited above). PS it is not usual to hide const inside the typedef. Normally the typedef only contains the struct part (and that is really only in C (not in C++). Then you use const explicitly around the code so it is obvious (sometimes const goes in the name but you should reflect that in the name of the typedef to make it obvious).
Martin York
A: 

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.

GMan
Ah! Of course! Thanks! As a side note, the handle definition is not mine and I cannot change it. I believe its predecessors may harken back to the 16-bit days. I'm not sure.
PaulH