shared_ptr with non-pointer resources

c++, c++11, shared-ptr

Solution

Sadly, `shared_ptr`'s need for type-erasure makes it impossible with the current interface to achieve exactly what you want. `unique_ptr` manages to do that because it has static information on the actual deleter type, from where it can draw the actual "pointer" type. In `shared_ptr`'s case, the deleter type is lost in the type-erasure process (which is why you can't specify it in the `shared_ptr` template).

Also note that `unique_ptr` doesn't provide any converting constructors like `shared_ptr` does (e.g. `template<class Y> shared_ptr(Y* p)`). It can't do so because `pointer` is not necessarily a real pointer type, and so it can't restrict what can be accepted (except maybe through some SFINAE with `std::is_convertible_to` or something like that... but I digress).

Now, one obvious workaround is to simply `new` the resource handle, as dumb as it sounds. :/

std::shared_ptr<SC_HANDLE> sp(new SC_HANDLE(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS)),
    [](SC_HANDLE* p){ ::CloseServiceHandle(*p); delete p; });

Problem

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?

Original source