可变大小的异构容器,按类型进行类型安全查找

时间:2015-02-19 14:48:45

标签: c++ c++11

我想实现实体组件系统,其中每个实体都有一个组件列表。每个组件都派生自 BaseComponent 类。实体中的每个组件都是唯一的 - 例如,实体不可能有两个 TransformComponent 组件。我想使用方法getComponent():

快速和类型安全地访问实体中的组件
template <typename T>
T * getComponent();

在实体中实现组件容器的最佳方法是什么?

PS:我有很多实体(大约10-20万),每个实体有大约2-3个组件,10个是最大组件。所以我担心 unordered_map 对我的任务来说太重了。

2 个答案:

答案 0 :(得分:1)

我建议将元组方法作为一个稻草人,以确定您的其他要求是什么:

#include <utility>

template <typename...Components>
class Entity : private Components... {
public:
    Entity() = default;

    Entity(Components...components) :
        Components(std::move(components))... {}

    template <typename T>
    T& get() {
        return *this;
    }
    template <typename T>
    const T& get() const {
        return *this;
    }
};


#include <iostream>

struct ComponentA { void f() const { std::cout << "I'm a ComponentA\n"; } };
struct ComponentB { void f() const { std::cout << "I'm a ComponentB\n"; } };
struct ComponentC { void f() const { std::cout << "I'm a ComponentC\n"; } };

int main() {
    {
        Entity<ComponentA, ComponentB, ComponentC> e;
        e.get<ComponentC>().f();
        e.get<ComponentB>().f();
        e.get<ComponentA>().f();
    }

    {
        ComponentA a;
        Entity<ComponentA, ComponentB> e{a, {}};
    }

    {
        // error: duplicate base type
        // Entity<ComponentA, ComponentA> invalid_entity;
    }
}

它的优点是所有类型都是具体的,Component类型甚至不需要相关。

答案 1 :(得分:0)

我决定使用简单方法在 Entity 中包含数组* BaseComponent m_comps [MAX_COMPONENTS] ,并为每个组件类型分配唯一ID。因为组件类型的数量限制为20-30。通过这种方式,我可以最快地访问组件,只需要在实体内部存储20-30个指针(并且它们将分配在一个块中,实体本身允许良好的缓存局部性)

我使用此代码进行类型安全访问:

template <typename T>
T * Entity::getComp()
{
  return (T*)m_comps[T::idCompType];
}

并且每个组件都应该声明const静态成员 idCompType