我想使用boost :: shared_ptr<>封装句柄的生命周期管理。我的句柄和它的创建/销毁函数声明如下:
typedef const struct MYHANDLE__ FAR* MYHANDLE;
void CloseMyHandle( MYHANDLE );
MYHANDLE CreateMyHandle();
理想情况下,我想像这样使用boost::shared_ptr<>
来管理句柄:
boost::shared_ptr< void > my_handle( CreateMyHandle(), &CloseMyHandle );
不幸的是,因为句柄被声明为const struct *
而不是通常的void *
,所以我得到这样的错误:
boost/smart_ptr/shared_ptr.hpp(199) : error C2440: 'initializing' : cannot convert from 'const MYHANDLE__ *' to 'void *'
我可以使用仿函数将void *
投射到这样的MYHANDLE
:
struct DeallocateMyHandle
{
void operator()( void* handle )
{
CloseMyHandle( ( MYHANDLE )handle );
};
};
boost::shared_ptr< void > my_handle( ( void* )CreateMyHandle(), DeallocateMyHandle() );
但是,我宁愿有一个不涉及单独的仿函数的方法。有没有办法在我看不到的boost::shared_ptr<>
构造函数中执行此操作?或者,我是否坚持使用仿函数?
谢谢, PaulH
答案 0 :(得分:4)
为什么不使用:
boost::shared_ptr< const MYHANDLE__ > my_handle( CreateMyHandle(), &CloseMyHandle );
PS。请注意,不允许使用双下划线(它是为实现保留的) 请参阅:Rules about identifers
答案 1 :(得分:2)
如果HANDLE是一个公共类型,但它所指的类型不是,那么写一个非常简单的方法:
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);
(如果您使用的是旧版本的VC ++或gcc,则可能需要省略“typename”。)
当然这有点冗长乏味。如果你只有一个句柄类型可以处理,你可能会这样写:
typedef typename unpointer<MYHANDLE>::type MYHANDLEREF;
typedef boost::shared_ptr<MYHANDLEREF> my_shared_ptr;
如果你有各种各样的句柄来包装(并且因为它看起来你正在做Win32 API的事情,你可能会这样做),创建一个模板,在你喜欢的任何级别包装东西(一个类模板,只需生成类型,handle_ptr<T>
子类shared_ptr<unpointer<T>>
并为您添加默认值,handle_ref<T>
在幕后使用shared_ptr
假冒{{1}而不是伪造成MYHANDLE &
是指针等等。)
答案 2 :(得分:0)
您的shared_ptr
类型必须是这样的:
boost::shared_ptr< const MYHANDLE__ FAR>
当shared_ptr
指出一个指针时,它变为:
const MYHANDLE__ FAR*
与您的MYHANDLE
类型完全匹配:
#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 );
}
注意,我确实怀疑你需要FAR
,这是16位年龄。它会扩展为far
或者没有任何内容,具体取决于您是否正在编译16位(提示:您没有编译为16位。:))。据我所知,far
甚至不再是延伸。
另外,就像马丁所说的那样,不要在任何地方使用双下划线。