【发布时间】:2014-07-07 13:01:26
【问题描述】:
相关主题
std::unique_ptr, deleters and the Win32 API
要将 Win32 句柄用作 RAII,我可以使用以下行
std::unique_ptr<std::remove_pointer<HANDLE>::type, decltype(&CloseHandle)> m_mutex(CreateMutex(NULL, FALSE, NULL), &::CloseHandle);
对我来说,这是一个干净的单线,完全符合我的要求。
当涉及到 SOCKET 时,由于 SOCKET 不能为 nullptr,因此它不会使用同一行编译。
我需要做的事情如下:
struct SocketDeleter
{
typedef SOCKET pointer;
void operator()(SOCKET h)
{
::closesocket(h);
}
};
// Start listen socket.
std::unique_ptr<SOCKET, SocketDeleter> sock(socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_UDP));
在这个实现中我不喜欢的是我想要使用的任何不同类型的资源,我需要复制/粘贴相同的代码来只更改关闭函数。
我可以使用宏,但这真的很丑,不能使用两次
#define RAII_UNIQUE_RESOURCE(varName, classType, init, closure) \
struct deleterMacro \
{ \
typedef classType pointer; \
void operator()(classType h) \
{ \
closure(h); \
} \
}; \
std::unique_ptr<classType, deleterMacro> varName(init);
// Compile, but breaks as soon as 2 sockets defined.
RAII_UNIQUE_RESOURCE(sock, SOCKET, socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_UDP), ::closesocket);
我尝试使用模板,但据我所知,我无法将函数指针传递给 operator() 函数。
template<class T, class methodDeclaration, class pFuncPointer>
struct deleter
{
typedef T pointer;
void operator()(T h)
{
// Is there a way??
methodDeclaration toCall = pFuncPointer;
toCall(h);
}
};
// With a call such as ...
std::unique_ptr<SOCKET, deleter<SOCKET, std::function<decltype(::closesocket)>, ::closesocket>> sock2(socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_UDP));
【问题讨论】:
-
你可能想要这样的东西:
template <typename T, typename D, D Deleter> struct stateless_deleter { using pointer = T; void operator()(T x) { Deleter(x); } };用法:std::unique_ptr<Socket, stateless_deleter<Socket, void(*)(Socket), &CloseSocket> p(OpenSocket()); -
为什么要打扰
std::unique_ptr?编写一个 RAII 包装器需要 5 分钟,谷歌搜索需要 30 秒。 -
@Drop 为什么要编写自定义功能如果有一个标准功能?
-
@UmNyobe 如果有一个。正如我所见,没有这样的。