Related topic
std::unique_ptr, deleters and the Win32 API
To use a Win32 Handle as a RAII, I can use the following line
std::unique_ptr<std::remove_pointer<HANDLE>::type, decltype(&CloseHandle)> m_mutex(CreateMutex(NULL, FALSE, NULL), &::CloseHandle);
For me this is a clean one-liner and does exactly what I want.
When it comes to SOCKET, it won't compile with this same line since SOCKET cannot be nullptr.
What I need to do to make it work is the following :
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));
What I don't like in this implementation is that any different type of ressources I'll want to use, I'll need to copy/paste the same code to only change the closing function.
I could use a Macro, but this is really ugly and can't be used twice
#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);
I tried to use a template, but I cannot pass my function pointer to the operator() function, as far as I know.
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); } };
Usage:std::unique_ptr<Socket, stateless_deleter<Socket, void(*)(Socket), &CloseSocket> p(OpenSocket());
– Smackstd::unique_ptr
? It will take 5 minutes to write a RAII wrapper or 30 sec to Google it up. – Kannullptr
, it just has to be comparable-tonullptr
(I think it is called NullablePointer). I have written a class that implements that for non-pointer-like types, if anybody is interested... – Counterweightstruct
is just 4 lines. I've posted my code as an answer. – Counterweight