在 VC2012 中,我想使用唯一指针和删除器在构造函数中创建互斥锁,这样我就不需要创建析构函数来调用 CloseHandle.
In VC2012, I want to create a mutex in a constructor using a unique pointer and a deleter, so that I don't need to create a destructor just to call 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 *'
当我这样修改构造函数时:
When I modify the constructor thus:
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* 的 typedef:是否有一些我需要了解的转换魔法?
I'm at a loss now. HANDLE is a typedef for void*: is there some conversion magic I need to know about?
暂时忘记自定义删除器.当你说 std::unique_ptr
时,unique_ptr
构造函数期望接收一个 T*
,但 CreateMutex
> 返回一个 HANDLE
,而不是一个 HANDLE *
.
Forget about the custom deleter for now. When you say std::unique_ptr<T>
, the unique_ptr
constructor expects to receive a T*
, but CreateMutex
returns a HANDLE
, not a HANDLE *
.
有 3 种方法可以解决此问题:
There are 3 ways to fix this:
std::unique_ptr<void, deleter> m_mutex;
您必须将 CreateMutex
的返回值转换为 void *
.
You'll have to cast the return value of CreateMutex
to a void *
.
另一种方法是使用 std::remove_pointer
获取HANDLE
的底层类型.
Another way to do this is use std::remove_pointer
to get to the HANDLE
's underlying type.
std::unique_ptr<std::remove_pointer<HANDLE>::type, deleter> m_mutex;
另一种方法是利用以下事实:如果 unique_ptr
的删除器包含名为 pointer
的嵌套类型,则 unique_ptr
code> 将使用该类型作为其托管对象指针而不是 T*
.
Yet another way to do this is to exploit the fact that if the unique_ptr
's deleter contains a nested type named pointer
, then the unique_ptr
will use that type for its managed object pointer instead of T*
.
struct mutex_deleter {
void operator()( HANDLE h )
{
::CloseHandle( h );
}
typedef HANDLE pointer;
};
std::unique_ptr<HANDLE, mutex_deleter> m_mutex;
foo() : m_mutex(::CreateMutex(NULL, FALSE, NULL), mutex_deleter()) {}
<小时>
现在,如果要传递函数类型的指针作为删除器,那么在处理Windows API时还需要注意创建函数指针时的调用约定.
Now, if you want to pass a pointer to function type as the deleter, then when dealing with the Windows API you also need to pay attention to the calling convention when creating function pointers.
所以,一个函数指针指向 CloseHandle
必须像这样
So, a function pointer to CloseHandle
must look like this
BOOL(WINAPI *)(HANDLE)
综合起来,
std::unique_ptr<std::remove_pointer<HANDLE>::type,
BOOL(WINAPI *)(HANDLE)> m_mutex(::CreateMutex(NULL, FALSE, NULL),
&::CloseHandle);
我发现使用 lambda 更容易
I find it easier to use a lambda instead
std::unique_ptr<std::remove_pointer<HANDLE>::type,
void(*)( HANDLE )> m_mutex;
foo() : m_mutex(::CreateMutex(NULL, FALSE, NULL),
[]( HANDLE h ) { ::CloseHandle( h ); }) {}
或者按照@hjmd 在注释中的建议,使用 decltype
来推断函数指针的类型.
Or as suggested by @hjmd in the comments, use decltype
to deduce the type of the function pointer.
std::unique_ptr<std::remove_pointer<HANDLE>::type,
decltype(&::CloseHandle)> m_mutex(::CreateMutex(NULL, FALSE, NULL),
&::CloseHandle);
这篇关于std::unique_ptr、删除器和 Win32 API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!