在VC2012中,我想使用唯一指针和删除器在构造函数中创建一个互斥锁,这样我就不需要仅为调用CloseHandle而创建析构函数。
我本以为这会奏效:
struct foo
{
std::unique_ptr<HANDLE, BOOL(*)(HANDLE)> m_mutex;
foo() : m_mutex(CreateMutex(NULL, FALSE, NULL), CloseHandle) {}
}
但是编译时我得到一个错误:
error C2664: 'std::unique_ptr<_Ty,_Dx>::unique_ptr(void *,int
(__cdecl *const &)(HANDLE)) throw()' : cannot convert parameter 1 from
'HANDLE' to 'void *'
当我这样修改构造函数时:
foo() : m_mutex((void*)CreateMutex(NULL, FALSE,
(name + " buffer mutex").c_str()), CloseHandle) {}
我得到了更不寻常的:
error C2664: 'std::unique_ptr<_Ty,_Dx>::unique_ptr(void *,
int (__cdecl *const &)(HANDLE)) throw()' : cannot convert
parameter 1 from 'void *' to 'void *'
我现在很困惑,HANDLE是void* 的类型定义:有什么转化魔法需要我知道吗?
3条答案
按热度按时间wtlkbnrh1#
现在先不考虑自定义删除器,当您使用
std::unique_ptr<T>
时,unique_ptr
构造函数期望接收T*
,但是CreateMutex
返回HANDLE
,而不是HANDLE *
。有3种方法可以解决此问题:
您必须将
CreateMutex
的返回值强制转换为void *
。另一种方法是使用
std::remove_pointer
获取HANDLE
的底层类型。另一种方法是利用这样的事实,即如果
unique_ptr
的删除器包含名为pointer
的嵌套类型,则unique_ptr
将使用该类型而不是T*
作为其托管对象指针.现在,如果你想传递一个指向函数类型的指针作为删除器,那么在处理Windows API时,你还需要注意创建函数指针时的调用约定。
因此,指向
CloseHandle
的函数指针必须如下所示把所有的一切结合起来,
我发现使用lambda更容易
或者按照注解中@hjmd的建议,使用
decltype
来推导函数指针的类型。zbdgwd5y2#
其他人已经指出了整个
HANDLE
/HANDLE*
问题是如何工作的,下面是一个更聪明的方法来处理它,使用std::unique_ptr
有趣的特性。这允许
unique_handle::get
返回HANDLE
而不是HANDLE*
,而不需要任何花哨的std::remove_pointer
或其他类似的东西。这是因为
HANDLE
是一个指针,因此满足NullablePointer。62lalag43#
问题是您实际上定义了unque_ptr来保存指向句柄(HANDLE*)类型的指针,但是您只传递了HANDLE,而没有传递指向它的指针。