具有模板类型的动态类型单例。这是一种可行的方法吗? [解决方案提供]

时间:2014-02-14 01:11:42

标签: c++ templates singleton directx-11 dynamictype

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

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,但这意味着每次调用 纹理管理器需要所需的类型作为模板参数,这有点类似于抽象这一点。

请帮助男女,请在评论中提出建设性意见。 请询问我是否遗漏了关键/所有细节。大脑太累了,无法思考。 谢谢

1 个答案:

答案 0 :(得分:2)

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

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

这有点粗糙,但希望你明白了。