2

質問はわかりにくいかもしれませんが、問題は非常に単純なので、ここでは簡単な言葉で説明します。現在、私のリソース管理は次のとおりです。

    cResMgr<cTexture> textures;
    cResMgr<cSound> sounds;

私がやりたいことは:

    cResMgr resources;
    resources.add<cTexture>(...);
    resources.get<cSound>(...);

基本的に、私のリソースマネージャーには「get」関数と「add」関数があります。cWhateverタイプの関数を最初に呼び出すときに、そのコンテナーが作成されるようにしたいと思います。次回呼び出されるときは、そこにあるだけです(関数の静的変数に似ています)

問題は、どうすればそれを実装できるかということです。私が考えることができる唯一の解決策は、空の基本クラスcResourceから派生するすべてのリソースを用意することです。これにより、cResourceへのポインターのコンテナーを1つ持つことができます。問題は、リソースタイプが私のものではないことです(それらは外部ライブラリからのものです)

解決策はありますか?

4

3 に答える 3

2

リソースタイプごとに異なるリソースマネージャーを使用しない理由がよくわかりません。

また、コレクションがグローバルに静的であっても問題ないのであれば、なぜリソース マネージャーのインスタンスが必要なのでしょうか?

とにかく、これはあなたが説明したことをするはずです:

#include <string>
#include <map>

typedef double cTexture;
typedef std::string cSound;

struct cResMgr
{
    template <typename T>
        void add(std::string const& id, T const& v) const
        {
            mapFor<T>()[id] = v;
        }

    template <typename T>
        T& get(std::string const& id) const
        {
            return mapFor<T>().at(id);
        }

    private:
    template <typename T>
    static std::map<std::string, T> mapFor()
    {
        static std::map<std::string, T> _theMap;
        return _theMap;
    }
};

int main()
{
    cResMgr resources;
    resources.add<cTexture>("wall", cTexture {});
    resources.get<cSound>("sad_trombone");
}
于 2013-02-08T22:02:17.560 に答える
1

地図が使えます。もちろん、これは実行時に解決されます。これは、コンパイル時に可能な限り解決するというテンプレートの目標を打ち破ります。また、コンテナには抽象的な基本クラスがないため、コンテナは少し注意が必要です。Boost.Anyを使用します。これは次のようになります。

template<res_type>
container<res_type>& get()
{
     map<type_info, boost::any>::iterator it = map.find(typeid(res_type));
     if(it == map.end())
         map[typeid(res_type)] = container<res_type>();
     boost::any& c = map[typeid(res_type)];
     return boost::any_cast<container<res_type> >(c);
}

私はこれをコンパイルしませんでしたが、それが意味を理解することを願っています。最後に、1つの質問です。本当に多くの異なるタイプがあるので、これはすべて面倒な価値がありますか、それとも好奇心ですか。

于 2013-02-08T22:05:38.123 に答える
1

型消去の目的で基本クラスを使用して正しい方向に進んでおり、リソースマネージャーにそのリソースへのポインターを保持させることができました。あなたが暗示しているように、あなたのリソースシステムのユーザーに彼らのリソースを基本クラスから派生させることは不合理な負担です。

したがって、あなたがする必要があるのは、リソースをラップするためのカップルクラスを作成することです...

class ResourceBase
{
    /*...*/
};

template<typename T>
class Resource : public ResourceBase
{
    /* contains a T. T is the user's resource */
};

次に、リソースマネージャーにResourceBaseポインターのリストを含めることができます。ユーザーがポインタresources.get<cSound>("sound7");を検索できると言ったらResourceBase(ポインタがある場合)、それをにダウンキャストしてResource<cSound>、含まれているものを返しcSoundます。

于 2013-02-08T22:03:02.637 に答える