Yes. I have done that for Windows native RPC handles.
The problem is, we have to specify the custom deleter each time when we declare a new variable. It's tedious. Maybe a typedef or "using"?
And, std::unique_ptr lacks abstraction for a default_value.
Also, we can add custom conversion operator for UniqueResource to avoid explicitly using
Get() method each time, just like "operator LPCSTR()", and "operator LPCWSTR()" of the ancient CString class from Microsoft.
Code:
explicit operator ResourceType() const noexcept
{
return resource_;
}
"explicit" can be omitted if you prefer convenience to safety.
samples of custom deleters for windows native RPC( "pointer" is defined for each functor):
Code:
struct StringBindingDeleter {
typedef RPC_WSTR pointer;
void operator()(RPC_WSTR stringBinding) {
[[maybe_unused]] RPC_STATUS status = RpcStringFree(&stringBinding);
assert(status == RPC_S_OK);
}
};
struct RpcBindingDeleter {
typedef RPC_BINDING_HANDLE pointer;
void operator()(RPC_BINDING_HANDLE h) {
[[maybe_unused]] RPC_STATUS status = RpcBindingFree(&h);
assert(status == RPC_S_OK);
}
};
usage:
Code:
RPC_WSTR stringBinding = nullptr;
status = RpcStringBindingCompose(nullptr, (RPC_WSTR)L"ncalrpc", nullptr,
(RPC_WSTR)L"9038a9dd-b0f3-4745-827e-d4109e662cea", nullptr,
(RPC_WSTR *)&stringBinding);
if (status != RPC_S_OK || !stringBinding)
return E_FAIL;
std::unique_ptr stringBindingOwner(stringBinding, StringBindingDeleter);
RPC_BINDING_HANDLE rpcBinding = nullptr;
status = RpcBindingFromStringBinding(stringBinding, &rpcBinding);
if (status != RPC_S_OK)
return E_FAIL;
std::unique_ptr rpcBindingOwner(rpcBinding, RpcBindingDeleter);
Quote:
Originally Posted by atom0s
You can also do something similar to this by using the built-in 'std::shared_ptr' type. It allows for initialization with a custom deleter function. With that, you can pass a type cleanup call for types that have one. (You can also just define your own callback to cleanup custom/more unique types as needed.)
For example, using a 'HANDLE' type, which is cleaned up using 'CloseHandle':
Code:
const std::shared_ptr handle(::OpenProcess(PROCESS_VM_READ, FALSE, pid), ::CloseHandle);
Usage is then similar to your setup by just using 'handle.get()' to obtain the actual handle.
|