3

Let's say I have a class called Derived, which inherits from a class called Base. Base is special - though it may be created using new, it has to be destructed through a custom deleter.

I would like to have the Base in an unique_ptr along with the custom deleter called BaseDeleter. This also allows me to have other classes that derive from Base assigned to it. And for the sake of exception-safety and consistency I'd like to use std::make_unique to assing my unique_ptr.

I created a small snippet that demonstrates what I want:

#include <memory>

class Base
{
};

class Derived : public Base
{
};

struct BaseDeleter
{
    void operator()(Base* base)
    {
        // Perform some special deleting
    }
};

class Big
{
public:
    Big()
    {
        //pointer.reset(new Derived()); // This works!
        pointer = std::make_unique<Derived, BaseDeleter>(); // But this doesn't...
    }

private:
    std::unique_ptr<Base, BaseDeleter> pointer;
};

int main()
{
    Big clazz;
}

Unfortunately this fails to compile on both Visual Studio 2015 Update 2 and gcc-5.1. (ideone)
Why does this not work? How could one use std::make_unique to assign such a std::unique_ptr?

tambre
  • 4,625
  • 4
  • 42
  • 55

2 Answers2

8

This is (one of) the signature(s) of make_unique, the one that I guess you expect to be used:

template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args );

Where T is the type of the object you want to create, Args... are the types of the arguments you are to forward to the constructor.

As you can see, you cannot indicate a custom deleter with the make_* helper functions for smart pointers (neither with make_unique, nor with make_shared).

You have to explicitly construct your pointer as it follows:

std::unique_ptr<T, D> ptr{new T{)};

If the deleter is not default constructible, you can do this:

std::unique_ptr<T, D> ptr{new T{}, d};

Where d is an instance of the deleter.

skypjack
  • 49,335
  • 19
  • 95
  • 187
4

Make unique does not work with custom deleters. Write your own or do not use it.

This has nothing to do with the base/derived complication in your question, which is a red herring.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524