0

So I'm just experimenting with smart pointers and how I can manage Win32 HANDLE objects with them, so I wanted to test out this simple code I wrote.

It's supposed to provide a custom deleter for std::unique_ptr to use when the smart pointer goes outta scope.

template <typename Function>
class PtrDeleter
{
    Function _Closer;
public:
    void operator()(void* memBlock) const
    {
        _Closer(memBlock);
    }
};

//The std::make_unique is the one causing the problem...
std::unique_ptr<void*, PtrDeleter<decltype(CloseHandle)>> ptr = std::make_unique<void*>(OpenThread(...));

The reason I'm using a template for the Function parameter is because I'll be using other functions with CloseHandle, like CoTaskMemFree.

cannot convert from std::unique_ptr<void *,std::default_delete<_Ty>>' to 'std::unique_ptr<void *,PtrDeleter<BOOL (HANDLE)>>

This is what the compiler is outputting. Why is it still trying to use std::default_delete with std::make_unique?

Arush Agarampur
  • 1,340
  • 7
  • 20
  • 1
    Does this answer your question? [Using std::make\_unique with a custom deleter](https://stackoverflow.com/questions/21788066/using-stdmake-unique-with-a-custom-deleter) – Scheff's Cat Feb 23 '21 at 06:18
  • The [WIL](https://github.com/microsoft/wil) implements that already. Have a look at the [RAII resource wrappers](https://github.com/Microsoft/wil/wiki/RAII-resource-wrappers). – IInspectable Feb 23 '21 at 08:19

2 Answers2

4

make_unique returns unique_ptr with defaulted deleter.

To provide your custom version you have to call unique_ptr(Pointer,Deleter) version of unique_ptr ctor:

template <typename Function>
class PtrDeleter {
    Function _Closer;
public:
    void operator()(void* memBlock) const {
        _Closer(memBlock);
    }
};

int main() {
    PtrDeleter<decltype(&CloseHandle)> deleter;
    void* openThread = OpenThread(0,false,0);
    std::unique_ptr<void, decltype(deleter)> ptr(openThread,deleter);
}

Demo

rafix07
  • 20,001
  • 3
  • 20
  • 33
  • `make_unique` also allocates the object on the heap, which is not what we want here. That function is not at all suitable here. It also doesn't have any performance benefits like `make_shared` has compare to naked `new`. – Aykhan Hagverdili Feb 23 '21 at 07:03
3

std::make_unique cannot make std::unique_ptr with a custom deleter. You have to manually call its constructor.

std::unique_ptr<void*, PtrDeleter<decltype(&CloseHandle)>> ptr{nullptr, CloseHandle}

In your case, it can be simplified to

std::unique_ptr<void*,decltype(&CloseHandle)> ptr{nullptr, CloseHandle}

No need to make a functor.

김선달
  • 1,485
  • 9
  • 23