Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't return nullptr for unique_ptr return type

I am writing a wrapper for SDL_Texture* raw pointer which returns a unique_ptr.

using TexturePtr = std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>;

TexturePtr loadTexture(SDL_Renderer* renderer, const std::string &path) {
    ImagePtr surface =
        loadImage(path);
    if (surface) {
        return TexturePtr(
            SDL_CreateTextureFromSurface(renderer, surface.get())
            , SDL_DestroyTexture);
    }
    return nullptr;
}

But it gives following error:

no suitable constructor exists to convert from "std::nullptr_t" to "std::unique_ptr<SDL_Texture, void (__cdecl *)(SDL_Texture *texture)>"

As per my understanding it's acceptable to pass a nullptr in lieu of unique_ptr. I event tried passing an empty unique_ptr on the last return:

return TexturePtr();

but get similar error during build.

Please let me know what I am doing wrong here.

Env: compiler: Visual C++ 14.1

like image 551
dheeraj suthar Avatar asked May 09 '19 17:05

dheeraj suthar


People also ask

Can I assign Nullptr to unique_ptr?

It will work. unique_ptr& operator=(nullptr_t) noexcept ; Effects: reset() .

What happens when you return a unique_ptr?

If a function returns a std::unique_ptr<> , that means the caller takes ownership of the returned object. class Base { ... }; class Derived : public Base { ... }; // Foo takes ownership of |base|, and the caller takes ownership of the returned // object.

Is null and Nullptr the same?

nullptr is a keyword that can be used at all places where NULL is expected. Like NULL, nullptr is implicitly convertible and comparable to any pointer type. Unlike NULL, it is not implicitly convertible or comparable to integral types.

What is the default value of unique_ptr?

std::unique_ptr::unique_ptr default constructor (1), and (2) The object is empty (owns nothing), with value-initialized stored pointer and stored deleter.


1 Answers

The unique_ptr(nullptr_t) constructor requires that the deleter be default constructible and that it not be a pointer type. Your deleter does not satisfy the second condition because the deleter is a pointer to function. See [unique.ptr.single.ctor]/1 and [unique.ptr.single.ctor]/4.

This restriction is a good thing because default constructing your deleter results in a nullptr and undefined behavior, likely resulting in a segfault, when you try to invoke the deleter.

You can change your return statement to

return TexturePtr{nullptr, SDL_DestroyTexture};  // or just {nullptr, SDL_DestroyTexture}

Alternatively, provide a deleter that satisfies the above requirements. One such option is shown in another answer I wrote here.

like image 115
Praetorian Avatar answered Sep 19 '22 12:09

Praetorian