Hi,
I have some original code that manages exception safety like this:
void foo() {
HDC hdc = //get an HDC
HBITMAP hbitmap = //get an HBITMAP
HGDIOBJ hbitmapOld = SelectObject(hdc, hbitmap);
try {
//do something that may throw an exception
} catch (...) {
SelectObject(hdc, hbitmapOld);
throw;
}
}
Now I want to get rid of the try block and use unique_ptr to select the old bitmap automatically. So I wrote something like this:
void foo() {
//...
//HGDIOBJ is defined as void*
std::unique_ptr<void, std::function<HGDIOBJ(HGDIOBJ)>>
hbitmapOld(SelectObject(hdc, hbitmap), std::bind(SelectObject, hdc, _1));
}
But it doesn't compile. How to make it right?
Error message:
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxcallfun(7): error C2664: 'HGDIOBJ (HDC,HGDIOBJ)' : cannot convert parameter 2 from 'boost::arg<I>' to 'HGDIOBJ'
1> with
1> [
1> I=1
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxbind1(292) : see reference to function template instantiation '_Ret std::tr1::_Callable_fun<_Ty,_Indirect>::_ApplyX<_Ret,_Arg&,boost::arg<I>&>(_Arg0,_Arg1) const' being compiled
1> with
1> [
1> _Ret=_Rx,
1> _Ty=HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),
1> _Indirect=false,
1> _Arg=HDC,
1> I=1,
1> _Arg0=HDC &,
1> _Arg1=boost::arg<1> &
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxbind0(31) : see reference to function template instantiation '_Ret std::tr1::_Bind2<_Callable,_Arg0,_Arg1>::_ApplyX<_Rx,void&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&>(_Barg0,_Barg1,_Barg2,_Barg3,_Barg4,_Barg5,_Barg6,_Barg7,_Barg8,_Barg9)' being compiled
1> with
1> [
1> _Ret=_Rx,
1> _Callable=std::tr1::_Callable_fun<HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),false>,
1> _Arg0=HDC,
1> _Arg1=boost::arg<1>,
1> _Barg0=HGDIOBJ &,
1> _Barg1=std::tr1::_Nil &,
1> _Barg2=std::tr1::_Nil &,
1> _Barg3=std::tr1::_Nil &,
1> _Barg4=std::tr1::_Nil &,
1> _Barg5=std::tr1::_Nil &,
1> _Barg6=std::tr1::_Nil &,
1> _Barg7=std::tr1::_Nil &,
1> _Barg8=std::tr1::_Nil &,
1> _Barg9=std::tr1::_Nil &
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxcallobj(13) : see reference to function template instantiation 'void *std::tr1::_Bind_base<_Ret,_BindN>::operator ()<_Arg0&>(_Carg0)' being compiled
1> with
1> [
1> _Ret=HGDIOBJ ,
1> _BindN=std::tr1::_Bind2<std::tr1::_Callable_fun<HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),false>,HDC,boost::arg<1>>,
1> _Arg0=HGDIOBJ,
1> _Carg0=HGDIOBJ &
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxfunction(65) : see reference to function template instantiation '_Ret std::tr1::_Callable_obj<_Ty>::_ApplyX<_Rx,_Arg0&>(void)' being compiled
1> with
1> [
1> _Ret=HGDIOBJ,
1> _Ty=std::tr1::_Bind<HGDIOBJ,HGDIOBJ,std::tr1::_Bind2<std::tr1::_Callable_fun<HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),false>,HDC,boost::arg<1>>>,
1> _Rx=HGDIOBJ,
1> _Arg0=HGDIOBJ
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxfunction(64) : while compiling class template member function 'HGDIOBJ std::tr1::_Impl_no_alloc1<_Callable,_Rx,_Arg0>::_Do_call(_Arg0)'
1> with
1> [
1> _Callable=_MyWrapper,
1> _Rx=HGDIOBJ ,
1> _Arg0=HGDIOBJ
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxfunction(386) : see reference to class template instantiation 'std::tr1::_Impl_no_alloc1<_Callable,_Rx,_Arg0>' being compiled
1> with
1> [
1> _Callable=_MyWrapper,
1> _Rx=HGDIOBJ ,
1> _Arg0=HGDIOBJ
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxfunction(369) : see reference to function template instantiation 'void std::tr1::_Function_impl1<_Ret,_Arg0>::_Reset0o<_Myimpl,_Fty,std::allocator<_Ty>>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=HGDIOBJ ,
1> _Arg0=HGDIOBJ ,
1> _Fty=std::tr1::_Bind<HGDIOBJ,HGDIOBJ,std::tr1::_Bind2<std::tr1::_Callable_fun<HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),false>,HDC,boost::arg<1>>>,
1> _Ty=std::tr1::_Function_impl1<HGDIOBJ ,HGDIOBJ >,
1> _Alloc=std::allocator<std::tr1::_Function_impl1<HGDIOBJ ,HGDIOBJ >>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\functional(113) : see reference to function template instantiation 'void std::tr1::_Function_impl1<_Ret,_Arg0>::_Reset<_Fx>(_Fty)' being compiled
1> with
1> [
1> _Ret=HGDIOBJ ,
1> _Arg0=HGDIOBJ ,
1> _Fx=std::tr1::_Bind<HGDIOBJ,HGDIOBJ,std::tr1::_Bind2<std::tr1::_Callable_fun<HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),false>,HDC,boost::arg<1>>>,
1> _Fty=std::tr1::_Bind<HGDIOBJ,HGDIOBJ,std::tr1::_Bind2<std::tr1::_Callable_fun<HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),false>,HDC,boost::arg<1>>>
1> ]
1> r:\programming\windows\biota\library\orchid\src\pixmap.cpp(182) : see reference to function template instantiation 'std::tr1::function<_Fty>::function<std::tr1::_Bind<_Result_type,_Ret,_BindN>>(_Fx)' being compiled
1> with
1> [
1> _Fty=HGDIOBJ (HGDIOBJ),
1> _Result_type=HGDIOBJ,
1> _Ret=HGDIOBJ,
1> _BindN=std::tr1::_Bind2<std::tr1::_Callable_fun<HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),false>,HDC,boost::arg<1>>,
1> _Fx=std::tr1::_Bind<HGDIOBJ,HGDIOBJ,std::tr1::_Bind2<std::tr1::_Callable_fun<HGDIOBJ (__stdcall *const )(HDC,HGDIOBJ),false>,HDC,boost::arg<1>>>
1> ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxcallfun(7): error C2664: 'HGDIOBJ (HDC,HGDIOBJ)' : cannot convert parameter 1 from 'boost::arg<I>' to 'HDC'
1> with
1> [
1> I=1
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>
1>Build FAILED.