为从其模板成员函数的调用中已知的类型创建新容器的类



这个问题可能很难理解,但问题很简单,我将在这里用简单的词来描述它。现在,我的资源管理是:

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

我想做的是:

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

基本上,我的资源管理器具有"获取"one_answers"添加"功能。当我第一次为cWhatever类型调用函数时,它会为它创建一个容器。当它下次被调用时,它就在那里(类似于函数中的静态变量)

问题是,我该如何实现它?我能想到的唯一解决方案是让每个资源都从空基类cResource派生,这样我就可以有一个指向cResource的指针容器。问题是,资源类型不是我的(它们来自外部库)

有什么解决方案吗?

我真的不知道为什么不按每种资源类型使用不同的资源管理器。

此外,如果集合可以全局静态,为什么需要资源管理器的实例

无论如何,这应该是你所描述的:

#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");
}

您使用了一个用于类型擦除目的的基类,并且让您的资源管理器持有指向其资源的指针,这是正确的。正如您所暗示的,让资源系统的用户从基类派生资源是一种不合理的负担。

因此,您需要创建一个couple类来包装资源。。。

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

您可以使用地图。当然,这是在运行时解决的,这有点违背了模板在编译时尽可能多地解决的目标。此外,容器会有点棘手,因为容器没有一些抽象基类。我会用Boost。任何一个都可以。然后看起来是这样的:

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

我没有编译这个,但我希望它能让人明白这一点。最后,有一个问题:你真的有这么多不同的类型,值得这么麻烦吗?还是好奇。

最新更新