No appropriate default constructor available for std::unique_ptr

我与影子孤独终老i 提交于 2019-12-10 11:29:45

问题


This is a continuation of my previous post. Since it has already been closed I decided to make a new post. I removed half of the code to make it more readable.

Some of the posts I read:

Smart pointers with SDL

Is it possible to use SDL2 with smart pointers?

Couple of questions about SDL_Window and unique_ptr

class cGraphics
{
public:
    //  Creator functions
    std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> Create_Window(int xWin, int yWin);

    //  ctor & dtor
    cGraphics() : m_Window(nullptr, SDL_DestroyWindow) {}
    cGraphics(int xWin, int yWin);
    ~cGraphics();
private:
    std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> m_Window;

};

cGraphics::cGraphics(int xWin, int yWin)
{
    m_Window = std::move(Create_Window(xWin, yWin));

    if (m_Window == nullptr)
    {
        throw "SDL_Window or SDL_Renderer not ready!";
    }
}

cGraphics::~cGraphics()
{
    IMG_Quit();
    SDL_Quit();
}

std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> cGraphics::Create_Window(int xWin, int yWin)
{
    return std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)>(SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xWin, yWin, SDL_WINDOW_SHOWN), SDL_DestroyWindow);
}

The compiler complains that:

'std::unique_ptr<SDL_Window,void (__cdecl *)(SDL_Window *)>::unique_ptr': no appropriate default constructor available

I understand that this error usually shows up when the compiler cannot locate a default constructor for some of the members. However this is not true as I explicitly declared a default value for the std::unique_ptr.

If the compiler is actually complaining about SDL_Window, which is an incomplete type (a C struct), what can I do about this?


回答1:


A std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> is not default constructable. That means in

cGraphics::cGraphics(int xWin, int yWin) ***
{
    m_Window = std::move(Create_Window(xWin, yWin));

    if (m_Window == nullptr)
    {
        throw "SDL_Window or SDL_Renderer not ready!";
    }
}

When you reach the part *** the compiler is going to try and default construct m_Window since you didn't do so in the member initialization list. That attempt from the compiler ro default construct m_Window is what causes the error. We can fix this by moving m_Window = std::move(Create_Window(xWin, yWin)); out of the constructor body and putting it in the member initialization list like

cGraphics::cGraphics(int xWin, int yWin) : m_Window(Create_Window(xWin, yWin))
{   
    if (m_Window == nullptr)
    {
        throw "SDL_Window or SDL_Renderer not ready!";
    }
}

If you don't want to do that then you can delegate to the default constructor and then assign to m_Window like you were doing originally. That would look like

cGraphics::cGraphics(int xWin, int yWin) : cGraphics()
{
    m_Window = Create_Window(xWin, yWin);

    if (m_Window == nullptr)
    {
        throw "SDL_Window or SDL_Renderer not ready!";
    }
}



回答2:


Here is how you defined your unique_ptr:

std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> m_Window;

That means, it's constructor has to be called with an instance of the custome deleter, in your case, function SDL_DestroyWindow - remember, you told the pointer what is deleter's type, not what the actual deleter (a function pointer in your case).

To make this code work, you have to properly construct your pointer with a deleter instance, for example:

cGraphics::cGraphics(int xWin, int yWin) : 
                     m_Window{Create_Window(xWin, yWin)} {...}


来源:https://stackoverflow.com/questions/50956579/no-appropriate-default-constructor-available-for-stdunique-ptr

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!