问题描述
在 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_ptrcode> 将使用该类型作为其托管对象指针而不是 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设计公司网站源码
织梦dede网页模板下载素材销售下载站平台(带会员中心带筛选)
财税代理公司注册代理记账网站织梦模板(带手机端)
成人高考自考在职研究生教育机构网站源码(带手机端)
高端HTML5响应式企业集团通用类网站织梦模板(自适应手机端)