2
votes

I am trying to use std::unique_ptr for my gdi+ objects due to the benefits of automatic memory management.

Look at this standart gdi+ C style code:

Gdiplus::Graphics* graphics = Gdiplus::Graphics::FromImage(image);
graphics->DrawRectangle(/* parameters */); // Working

I know that I can use a std::unique_ptr as follows:

std::unique_ptr<Gdiplus::Graphics> graphics(Gdiplus::Graphics::FromImage(image));
graphics->DrawRectangle(/* parameters */); // Working

Now I want to construct the std::unique_ptr with std::make_unique but I can't get it to compile.

I have tried the following:

std::unique_ptr<Gdiplus::Graphics> graphics = std::make_unique<Gdiplus::Graphics>(Gdiplus::Graphics::FromImage(image));
graphics->DrawRectangle(/* parameters */); // Not working

But I get the following conversion error: C2664 Conversion of 1 argument from "Gdiplus::Graphics" in "HDC" is not possible.

I am using the latest version of VS2015.

I thought std::make_unique it should be used like this:

std::unique_ptr<T> varName = std::make_unique<T>(argument with which an instance of T will be constructed);

What am I doing wrong?

2
I guess that FromImage allocates the memory for the Graphics object, and if this is the case you won't need make_unique.simon
Another note: Make sure that the Graphics object allocated are ment to be deallocated using delete, e.g. delete graphics;. Otherwise you need to use a custom deleter for your unique_ptr.simon

2 Answers

3
votes

Actually, std::make_unique<T>(args...) calls T::T(args...) (with proper forwardng). So in your case you are calling Gdiplus::Graphics constructor with type Gdiplus::Graphics*, which is not your desire. You don't want make unique here. But you can create your own function, which shortens a syntax a bit.

std::unique_ptr<Gdiplus::Graphics> make_graphics(/*whatever image is*/ image)
{
    return std::unique_ptr<Gdiplus::Graphics>(Gdiplus::Graphics::FromImage(image));
}

Also, as gurka mentioned in the comments, once std::unique_ptr gets out of scope, it's content is destroyed using delete operator. IF Gdiplus::Graphics* has to be destroyed using custom deallocation method, you have to provide it to std::unique_ptr constructor (like std::unique_ptr<T, decltype(destroy_T)>(arg, destroy_T)

0
votes

I thought std::make_unique it should be used like this:

std::unique_ptr<T> varName = std::make_unique<T>(argument with which an instance of T will be constructed);

Yes

What am I doing wrong?

You are not constructing a instance. You're calling a function which constructs a instance for you, so it is not possible to use std::make_unique here.