In C++11 is it possible to use shared_ptr to control non-pointer resources?
It is possible to use unique_ptr to manage non-pointer resources. This is done by implementing a custom deleter class which provides:
- A
typedef {TYPE} pointer;where{TYPE}is the non-pointer resource type operator()(pointer)which frees the controlled resource
...and then instantiating a unique_ptr with the custom deleter as the second template parameter.
For example, under Windows it is possible to create a unique_ptr which manages a service control handle. This handle type is not freed by calling delete, but by calling CloseServiceHandle(). Here is sample code which does this:
Custom Deleter
struct SvcHandleDeleter
{
typedef SC_HANDLE pointer;
SvcHandleDeleter() {};
template<class Other> SvcHandleDeleter(const Other&) {};
void operator()(pointer h) const
{
CloseServiceHandle(h);
}
};
typedef std::unique_ptr<SC_HANDLE,SvcHandleDeleter> unique_sch;
Instantiation
unique_sch scm(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS));
Is it possible to use shared_ptr to control a non-pointer resource as well?
According to the documentation, there are shared_ptr constructor overloads which take provide the means to provide a custom deleter class, but none of the constructors accept a resource type that is not either a pointer or a wrapper around a pointer.
How can this be done?
SC_HANDLEis a pointer type! Inwinsvc.h:DECLARE_HANDLE(SC_HANDLE). And inwinnt.h:#define DECLARE_HANDLE(n) typedef struct n##__{int i;}*nor#define DECLARE_HANDLE(n) typedef void *ndepending on some precompiler conditions.std::unique_ptr<void*>is different fromstd::unique_ptr<void>. More to the point, there are APIs where a handle can e.g. have integral type.DECLARE_HANDLEmacro, and so they are syntactically pointers too (not that they all point to real memory though). That opens the possibility to solve the OP sample problem usingstd::shared_ptr.