这是我上一篇文章的延续:(很抱歉,问题链)
No appropriate default constructor available for 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()
。