具有模板化类型的动态类型Singleton.这是可行的方法吗?[提供的解决方案]

Dynamic Type Singleton with templated types. Is this a viable approach? [Solution Provided]

本文关键字:类型 方法 解决方案 动态 Singleton      更新时间:2023-10-16

我目前正在开发自己的引擎,特别是图形界面,并试图使其能够在DirectX和openGL渲染之间进行选择。为此,我想要一个纹理管理器单例(我习惯于使用它的标准实现)。然而,在这种情况下,我希望能够在抽象功能的同时选择实例的动态类型。以下是我到目前为止的实现:

template <typename T>
class TextureManagerType 
{
public:
virtual ~TextureManagerType() = 0 {}

T* GetTexture(TEXTURE_ID texID)
{
std::map<TEXTURE_ID, T*>::const_iterator it = m_textures.find(texID);
if(it != m_textures.end())
{
return (*it)->second;
}
else
{
assert(0);
return 0;
}
}
bool Load(const std::string& texturePaths)
{
File f;
if(!f.Open(texturePaths))
{
ReportError("Fatal error! Could not open: " + texturePaths);
return false;
}
std::string str;
while(!f.EndOf())
{
if(!f.GetString(&str))
{
ReportError("Warning: Unexpected end of file in     texturepaths file: " + texturePaths); 
}
LoadTexture(str);
}
return true;
}
virtual T* LoadTexture(const std::string& texturePath) = 0;
protected:
std::map<TEXTURE_ID, T*> m_textures;
};

//Uncopyable is a base class with a disabled copy constructor 
class TextureManager : public Uncopyable
{
private:    
TheTextureManager();
public:
//T here is underlined in all three mentions as it is undefined 
static TextureManagerType<T>* Instance()
{
return m_pInstance;
}
static void SetDynamicType(TextureManagerType<T>* type)
{
m_pInstance = type;
}
static TextureManagerType<T>* m_pInstance;

//static TexManagerType* Instance()
//{
//  return m_pInstance;
//}
//static void SetDynamicType(TexManagerType* type)
//{
//  m_pInstance = type;
//}
//static TexManagerType* m_pInstance;
};
//Named to be consistent with normal singletons
typedef TextureManager TheTextureManager;

正如您所看到的,我牺牲了单例的RAII加成,需要将m_pInstance指针初始化为null。

//I want the singleton once set, to be able to be accessed thusly:
TheTextureManager::Instance()->DoTextureFunction();

我不希望每种类型的TextureManager都有一个单例,因为我希望能够控制每个派生管理器的寿命,同时保持全局可访问性。目前,我的系统根本无法工作,因为TextureManager::Instance的返回类型需要知道无法访问的模板化类型。

我尝试在TextureManager中嵌套TextureManagerType,但这意味着每次调用纹理管理器将需要所需的类型作为模板参数,这有点违背了抽象这一点。

请帮助男孩和女孩,请在你的评论中富有建设性。请询问我是否遗漏了关键/所有细节。大脑太累了,现在无法思考。谢谢

您可以为TextureManagerType定义一个抽象的、非模板化的接口,并使用它来引用纹理管理器singleton对象中的纹理管理器实现
为了做到这一点,您还需要纹理对象的多态表示,它可以是简单的联合类型或抽象基类,具有不同具体纹理类型的派生类
可能都是这样的:

union TextureContainer {
OpenGLTexture* oglt;
DirectXTexture* dxt;
};
class TextureManagerTypeBase 
{
public:
virtual ~TextureManagerType() = 0;
virtual TextureContainer GetTexture(TEXTURE_ID texID) = 0;
virtual TextureContainer LoadTexture(const std::string& texturePath) = 0;
//this looks like it only refers to other public
// methods, so it's staying here
virtual bool Load(const std::string& texturePaths)
{
...
}
};
template <typename T>
class TextureManagerType : public TextureManagerTypeBase
{
public:
// pretty much the same as before
// minus Load wich is defined in the base class
// plus wrapping T into a TextureContainer
...
};

//Uncopyable is a base class with a disabled copy constructor 
class TextureManager : public Uncopyable
{
private:    
TheTextureManager();
public:
//T here is underlined in all three mentions as it is undefined 
static TextureManagerTypeBase* Instance()
{
return m_pInstance;
}
static void SetDynamicType(TextureManagerTypeBase* type)
{
m_pInstance = type;
}
static TextureManagerTypeBase* m_pInstance;
};

这有点难,但希望你能明白。

相关文章: