0

初めてのゲームを作成しています。パックマンかスネークになります。DirectX 11 を使用する予定です。

現在、リソースマネージャーを書いています。一番使いやすいものにしたいのですが、デザインが良くないと思います。ここに私が書いたものがあります:

#pragma once

class Shader;
class Mesh;
class Texture;

typedef std::map<std::string, std::auto_ptr<Shader>>    shaders_map;
typedef std::map<std::string, std::auto_ptr<Mesh>>      meshes_map;
typedef std::map<std::string, std::auto_ptr<Texture>>   textures_map;

template<class C, class E>
inline int findElementInMap(const C& cont, E *ptr)
{
    C::const_iterator it = cont.begin();
    int i = 0;

    while(it != cont.end())
    {
        if(it->second.get() == ptr) // ERROR AT THIS LINE!!!!
            return i;

        i++;
        it++;
    }

    return -1;
}

class ResourceManager
{
public:
    ResourceManager(void);
    ~ResourceManager(void);

    template<class T>
    inline T* get(const std::string &name)
    {
        if(typeid(T) == typeid(Shader)) {
            return (T*)getShader(name);
        }
        else if(typeid(T) == typeid(Mesh)) {
            return (T*)getMesh(name);
        }
        else if(typeid(T) == typeid(Texture)) {
            return (T*)getTexture(name);
        }

        return nullptr;
    }

    Shader*     getShader(const std::string &name);
    Mesh*       getMesh(const std::string &name);
    Texture*    getTexture(const std::string &name);

    template<class T>
    inline bool add(T *ptr)
    {
        if(typeid(T) == typeid(Shader)) {
            return addShader((Shader*)((void*)ptr));
        }
        else if(typeid(T) == typeid(Mesh)) {
            return addMesh((Mesh*)((void*)ptr));
        }
        else if(typeid(T) == typeid(Texture)) {
            return addTexture((Texture*)((void*)ptr));
        }

        return false;
    }

    bool        addShader(Shader *ptr);
    bool        addMesh(Mesh *ptr);
    bool        addTexture(Texture *ptr);

    template<class E>
    inline void release(E *ptr)
    {
        if(typeid(E) == typeid(Shader)) {
            release<shaders_map, E>(shaders, (E*)((void*)ptr));
            return;
        }
        else if(typeid(E) == typeid(Mesh)) {
            release<meshes_map, E>(meshes, (E*)((void*)ptr));
            return;
        }
        else if(typeid(E) == typeid(Texture)) {
            release<textures_map, E>(textures, ptr);
        }
    }

        // THIS METHOD CAUSES PROBLEM
    template<class C, class E>
    void release(C &container, E *ptr)
    {
        assert(ptr != nullptr);

        int index = findElementInMap<C, E>(container, ptr);
        if(index < 0)
            return;

        C::iterator it = container.begin();
        it->second.release();
    }
private:
    shaders_map     shaders;
    meshes_map      meshes;
    textures_map    textures;
};

そして今コンパイルエラー:

error C2440: '==' : cannot convert from 'Shader *' to 'Mesh *'
int findElementInMap<C,E>(const C &,E *)' being compiled
      with
      [
          C=textures_map,
          E=Shader
      ]

そのため、コンテナーの型と要素の型が一致しません。それを機能させる方法についてのアイデアはありますか?

それとも、新しいリソース マネージャーを最初から作成する必要がありますか?

編集:それが私がこのクラスを使用する方法です:

    Shader *sh = new Shader();
    resourceManager.add<Shader>(sh);
    resourceManager.release<Shader>(sh);
4

1 に答える 1

2

それを行う多くの方法。

単純なオーバーロードで行うことができます:

bool        add(Shader *ptr){
    return addShader(ptr);
}
bool        add(Mesh *ptr){
    return addMesh(ptr);
}

bool        add(Texture *ptr){
    return addTexture(ptr);
}

または、テンプレートを使用する場合は、add メソッドと get メソッドをテンプレート メソッドにして、特化するだけです。

template<class T>
void add(T *ptr){

}

およびリソースの種類ごとに

template<>
ResourceManager<Texture>::add(Texture *ptr){
    return addTexture(ptr);
}

template<>
ResourceManager<Shader>::add(Shader *ptr){
    return addShader(ptr);
}

template<>
ResourceManager<Mesh>::add(Mesh *ptr){
    return addMesh(ptr);
}

別のよりクリーンなオプションは、ターゲット コンテナーを返すテンプレート メソッドを作成することです。

template<typename T>
std::map<std::string, std::auto_ptr<typename T> > &getContainer(){


}

タイプが与えられた良いコンテナを返すように特化する

template<>
std::map<std::string, std::auto_ptr<Mesh> > &ResourceManager::getContainer<Mesh>(){

    return meshes_map;
}
template<>
std::map<std::string, std::auto_ptr<Texture> > &ResourceManager::getContainer<Texture>(){

    return textures_map;
}
template<>
std::map<std::string, std::auto_ptr<Shader> > &ResourceManager::getContainer<Shader>(){

    return shader_map;
}

これにより、get メソッドが次のように要約されます。

 template<typename T>
    T* get(const std::string &name){
        return getContainer<T>().get(name);
    }

免責事項: これはただの急ごしらえです。私はそれをコンパイルしていません。

コンパイル エラーに関する編集: resourceManager.release<Shader>(sh); For the picture, replace E を release メソッドで Shader に呼び出すと、コンパイルできないことがわかります。release(textures, ptr) release メソッドをコンパイルするには、明示的にキャストする必要があります。

template<class E>
    inline void release(E *ptr)
    {
        if(typeid(E) == typeid(Shader)) {
            release<shaders_map, Shader>(shaders, (Shader*)((void*)ptr));
            return;
        }
        else if(typeid(E) == typeid(Mesh)) {
            release<meshes_map, Mesh>(meshes, (Mesh*)((void*)ptr));
            return;
        }
        else if(typeid(E) == typeid(Texture)) {
            release<textures_map, Texture>(textures, (Texture*)((void*)ptr));
        }
    }
于 2012-10-27T12:04:31.827 に答える