سؤال

I'm currently working on my own engine, in particular the graphical interface and trying to make it able to choose between DirectX and openGL rendering. For this purpose, I want to have a Texture Manager singleton (I'm used to using a standard implementation of this). However in this case I want to be able to choose the dynamic type of the instance while abstracting functionality. Here is my implementation so far:

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;

As you can see, I've sacrificed the RAII bonus of a singleton and need to initialise the m_pInstance pointer to null.

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

I don't want a singleton for each type of TextureManager as i'd like to be able to control the life span of each derived manager while maintaining global accessibility. Currently my system is NOT working at all as the return type for TextureManager::Instance requires knowing the templated type which is inaccessible.

I tried nesting TextureManagerType within TextureManager but that meant that each call to the texture manager would need the required type as a template parameter which kinda defeats the point of abstracting this.

Please help guys and girls and please be constructive in your comments. Please enquire if I've left out crucial/all details. Brain too tired to think right now. Thank you

هل كانت مفيدة؟

المحلول

You could define an abstract, non-templated interface for your TextureManagerType, and use that to refer to the texture manager implementation from texture manager singleton object.
In order to do that, you also need a polymorphic representation for your Texture objects, which could be something as simple as a union type, or an abstract base class, with derived classes for different concrete texture types.
It may all look something like this:

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

That's a bit rough, but hopefully you get the idea.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top