Using Std::Make_Unique with a Custom Deleter

Using std::make_unique with a custom deleter

The whole point of make_unique is to encapsulate the notion of "use new to create a T from given constructor arguments and use delete to destroy it".

If you wanted a custom deleter, you would also have to specify how to create the object, and then there would be nothing more gained from having the emplacing maker function.

I wrote some examples of custom maker functions for certain unique resource handles in this post.

Unique_ptr with custom deleter

You cannot use std::make_unique with a custom deleter. You’ll need to use the regular constructor instead:

auto unique = std::unique_ptr<A, Deleter>(new A(5), Deleter());

Of course this will still require you to fix the rest of your code: make the constructor of A public, and declare A before Deleter. And you’d need to replace new A(…) by the proper construction that matches the custom Deleter.

And it’s worth noting that this might leak memory if the Deleter constructor throws, so you need to make sure that it doesn’t do that.

Using std::make_unique with custom deleter on a derived class?

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.

How to use a custom deleter using WinAPI with std::make_unique?

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

How do I use a custom deleter with a std::unique_ptr member?

Assuming that create and destroy are free functions (which seems to be the case from the OP's code snippet) with the following signatures:

Bar* create();
void destroy(Bar*);

You can write your class Foo like this

class Foo {

std::unique_ptr<Bar, void(*)(Bar*)> ptr_;

// ...

public:

Foo() : ptr_(create(), destroy) { /* ... */ }

// ...
};

Notice that you don't need to write any lambda or custom deleter here because destroy is already a deleter.

using custom deleter with unique_ptr

Should be

unique_ptr<FILE, int(*)(FILE*)>(fopen("file.txt", "rt"), &fclose);

since http://en.cppreference.com/w/cpp/memory/unique_ptr

or, since you use C++11, you can use decltype

std::unique_ptr<FILE, decltype(&fclose)>

primr 5 edition. unique_ptr constructor from custom deleter function

std::unique_ptr doesn't have a constructor that only takes a custom deleter. You'd have to pass nullptr as the pointer value if you want a null pointer with a custom deleter.

On your second point, that is correct. They didn't add make_unique until c++14, for really no other reason than that C++11 was a huge revision and some features didn't make it in.

Can I succintly declare std::unique_ptr with custom deleter?

Let the language do the hard work!

#include <memory>

struct qdr_link_t;
qdr_link_t* new_qdr_link_t();
void free_qdr_link_t(qdr_link_t*);

template <typename T, typename Deleter>
auto make_unique_ptr(T* raw, Deleter deleter)
{
return std::unique_ptr<T, Deleter>(raw, deleter);
}

//std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
auto link = make_unique_ptr(new_qdr_link_t(), free_qdr_link_t);

Add std::forward to taste (if you care).


For C++11, you'll need to add the trailing return type -> std::unique_ptr<T, Deleter> to make_unique_ptr, or just put that in the "normal" return type.



Related Topics



Leave a reply



Submit