views:

81

answers:

3

Following the advice of this page, I'm trying to get shared_ptr to call IUnknown::Release() instead of delete:

IDirectDrawSurface* dds;
... //Allocate dds
return shared_ptr<IDirectDrawSurface>(dds, mem_fun_ref(&IUnknown::Release));

error C2784: 'std::const_mem_fun1_ref_t<_Result,_Ty,_Arg> std::mem_fun_ref(Result (_thiscall _Ty::* )(_Arg) const)' : could not deduce template argument for 'Result (_thiscall _Ty::* )(Arg) const' from 'ULONG (_cdecl IUnknown::* )(void)'

error C2784: 'std::const_mem_fun_ref_t<_Result,_Ty> std::mem_fun_ref(Result (_thiscall _Ty::* )(void) const)' : could not deduce template argument for 'Result (_thiscall _Ty::* )(void) const' from 'ULONG (__cdecl IUnknown::* )(void)'

error C2784: 'std::mem_fun1_ref_t<_Result,_Ty,_Arg> std::mem_fun_ref(Result (_thiscall _Ty::* )(_Arg))' : could not deduce template argument for 'Result (_thiscall _Ty::* )(Arg)' from 'ULONG (_cdecl IUnknown::* )(void)'

error C2784: 'std::mem_fun_ref_t<_Result,_Ty> std::mem_fun_ref(Result (_thiscall _Ty::* )(void))' : could not deduce template argument for 'Result (_thiscall _Ty::* )(void)' from 'ULONG (__cdecl IUnknown::* )(void)'

error C2661: 'boost::shared_ptr::shared_ptr' : no overloaded function takes 2 arguments

I have no idea what to make of this. My limited template/functor knowledge led me to try

typedef ULONG (IUnknown::*releaseSignature)(void);
shared_ptr<IDirectDrawSurface>(dds, mem_fun_ref(static_cast<releaseSignature>(&IUnknown::Release)));

But to no avail. Any ideas?

+1  A: 

Isn't the calling convention specifier a problem? Would this be OK?

void iUnk_delete(IUnknown* u) {
  u->Release();
}


return shared_ptr<IDirectDrawSurface>(dds, iUnk_delete);
jpalecek
Er, wow, that works. Thanks! Do you know why the answer to [this question](http://stackoverflow.com/questions/441306/make-shared-ptr-not-use-delete) uses `ptr_fun` at all?
BlueRaja - Danny Pflughoeft
+2  A: 

std::mem_fun_ref doesn't support stdcall calling conversion as well as std::mem_fun which you could use for pointers.

You could use boost::mem_fn instead. You should define BOOST_MEM_FN_ENABLE_STDCALL to work with COM methods.

shared_ptr<IDirectDrawSurface>( dds, boost::mem_fn(&IUnknown::Release) );
Kirill V. Lyadvinsky
+2  A: 

I know this maynot be what youa re after but just include ATLBase.h and then use the CComPtr template.

You then just use

 CComPtr< IDirect3DSurface9 > surf;
 pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &surf );

You can then copy it to another CComPtr and it handles all the AddRefs and Releases for you. Very useful template class.

Goz