首页 > 解决方案 > 没有可用于 std::unique_ptr 的适当默认构造函数std::unordered_map 内部

问题描述

这是我之前帖子的延续:(对不起,问题链)

没有可用于 std::unique_ptr 的适当默认构造函数

我遇到了类似的错误,这次是std::unique_ptr在一个std::unordered_map容器中:(对不起,我必须把整个代码)

class cGraphics
{
public:
    //  Creator functions
    std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> Create_Window(int xWin, int yWin);
    std::unique_ptr<SDL_Renderer, decltype(&SDL_DestroyRenderer)> Create_Renderer();
    bool Create_TextureMap(std::string texid, std::string texres, int r, int g, int b);         //  Using helper function Create_Texture()

    //  ctor & dtor

    cGraphics(int xWin, int yWin, std::string texid, std::string texres);
    ~cGraphics();

    //  Rendering
    void ClearScreen();
    bool SetRendererDrawColor(int r, int g, int b, int opaque);
    void RenderTexture(std::string texres, int xDes, int yDes);
    bool Show();
private:
    std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> m_Window;
    std::unique_ptr<SDL_Renderer, decltype(&SDL_DestroyRenderer)> m_Renderer;
    std::unordered_map<std::string, std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>> m_TextureMap;

    //  Private default ctor
    cGraphics() : m_Window(nullptr, SDL_DestroyWindow), m_Renderer(nullptr, SDL_DestroyRenderer) {}

    //  Creator helper
    SDL_Texture* CreateTextureRawPtr(std::string texres, int r, int g, int b);
    std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)> CreateTexture(std::string texres, int r, int g, int b);
};

cGraphics::cGraphics(int xWin, int yWin, std::string texid, std::string texres) : cGraphics()
{
    SDL_Init(SDL_INIT_VIDEO);

    m_Window = Create_Window(xWin, yWin);
    m_Renderer = Create_Renderer();

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

    /*if (m_Window == nullptr || m_Renderer == nullptr || !Create_TextureMap(texid, texres, 255, 255, 255))
    {
        throw "SDL_Window or SDL_Renderer not ready!";
    }*/
}

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

void cGraphics::ClearScreen()
{
    SDL_RenderClear(m_Renderer.get());
}

bool cGraphics::SetRendererDrawColor(int r, int g, int b, int opaque)
{
    SDL_SetRenderDrawColor(m_Renderer.get(), r, g, b, opaque);      //  Should use reset here
    return true;
}

void cGraphics::RenderTexture(std::string texres, int xDes, int yDes)
{
    SDL_Rect g_SrcRect = { 0, 0, 32, 32 };          //  hard-coded for test
    SDL_Rect g_DesRect = { xDes, yDes, 32, 32 };
    SDL_RenderCopy(m_Renderer.get(), m_TextureMap[texres].get(), &g_SrcRect, &g_DesRect);
}

bool cGraphics::Show()
{
    SDL_RenderPresent(m_Renderer.get());
}

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);
}

std::unique_ptr<SDL_Renderer, decltype(&SDL_DestroyRenderer)> cGraphics::Create_Renderer()
{
    SDL_Renderer* temprenderer = SDL_CreateRenderer(m_Window.get(), -1, 0);
    SDL_SetRenderDrawColor(temprenderer, 255, 255, 255, 0xff);
    return std::unique_ptr<SDL_Renderer, decltype(&SDL_DestroyRenderer)>(temprenderer, SDL_DestroyRenderer);
}


bool cGraphics::Create_TextureMap(std::string texid, std::string texres, int r, int g, int b)
{
    m_TextureMap.emplace(texid, CreateTexture(texres, r, g, b));
    return true;
}

SDL_Texture* cGraphics::CreateTextureRawPtr(std::string texres, int r, int g, int b)
{
    SDL_Surface* temp = IMG_Load(texres.c_str());
    //Set color key
    SDL_SetColorKey(temp, SDL_TRUE,
        SDL_MapRGB(temp->format, r, g, b));

    SDL_Texture* pTexture = SDL_CreateTextureFromSurface(m_Renderer.get(), temp);

    SDL_FreeSurface(temp);
    return pTexture;
}

std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)> cGraphics::CreateTexture(std::string texres, int r, int g, int b)
{
    return std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>(CreateTextureRawPtr(texres, r, g, b), SDL_DestroyTexture);
}

错误信息是:

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

这与上一个问题绝对相似,但有一个例外:唯一指针位于容器内部。我在想也许我可以把它std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>放在一个包装类中,并为编译器提供一个包装类的默认 ctor。但这肯定很麻烦,不知道有没有更好的办法。

另一件事是我使用了很多.get(),我现在明白这是错误的,因为它只返回唯一指针内的原始指针的副本。也许我应该使用.reset().

标签: c++constructorunique-ptr

解决方案


推荐阅读