Using std::unique_ptr for Windows HANDLEs
The implementation of unique_ptr
checks for the presence of a ::pointer
type on the deleter. If the deleter has a ::pointer
type then this type is used as the pointer
typedef on the unique_ptr
. Otherwise a pointer to the first template argument is used.
According to cppreference.com, the unique_ptr::pointer
type is defined as
std::remove_reference<D>::type::pointer
if that type exists, otherwiseT*
From the MSDN manual on unique_ptr:
The stored pointer to an owned resource,
stored_ptr
has type pointer. It isDel::pointer
if defined, andType *
if not. The stored deleter objectstored_deleter
occupies no space in the object if the deleter is stateless. Note that Del can be a reference type.
This means that if you provide a deleter functor it have to provide a pointer
type that is used for the actual pointer type of the unique_ptr
. Otherwise it will be the a pointer to your provided type, in your case HANDLE*
which isn't correct.
I've been doing the following for various types of handles in Windows. Assuming we have declared somewhere:
std::unique_ptr<void, decltype (&FindVolumeClose)> fv (nullptr, FindVolumeClose);
This is populated with:
HANDLE temp = FindFirstVolume (...);
if (temp != INVALID_HANDLE_VALUE)
fv.reset (temp);
No need to declare a separate struct to wrap the deleters. Since HANDLE
is really a void *
the unique_ptr
takes void
as its type; for other kinds of handles, that use the DECLARE_HANDLE
macro, this can be avoided:
// Manages the life of a HHOOK
std::unique_ptr<HHOOK__, decltype (&UnhookWindowsHookEx)> hook (nullptr, UnhookWindowsHookEx);
And so on.