代码之家  ›  专栏  ›  技术社区  ›  sjaustirni Keyki

如何使用模板创建编译时类字段?

  •  2
  • sjaustirni Keyki  · 技术社区  · 7 年前

    几乎没有背景和理由

    我正在设计一个编译时ECS。设计有其特殊性——例如,将有各种各样的实体。这意味着组件的总体数量可能相当高,而每个实体的组件数量将相当低(在几乎所有地方都有一些明显的共同点,例如 Sprite BoundingBox )

    我的方法

    我将实现以下接口:

    /* Tell the compiler which fields we would use in this entity */
    Entity<GraphicsComponent, PhysicsComponent> entity;
    
    /* Populate the handles with the appropriate data (integer, pointer, doesn't matter) */
    // via explicit creation
    Entity.add<GraphicsComponent>(RenderSystem::create<GraphicsComponent>());
    // or in some other way?
    

    成立 Entity 一班学生写道:

    template <typename ...>
    class Entity final {};
    

    然而,我不知道我该怎么做 为各个组件类型创建句柄数据字段 ,如果可能的话。有谁能帮我或解释一下为什么它不起作用(或者可能提出不同的解决方案)?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Caleth    7 年前

    只需使用 std::tuple . N、 b get 要求每个 Components... 是一种独特的类型

    template <typename ... Components>
    class Entity final { 
        std::tuple<Components...> components;  
        template<typename Component>
        void add(Component component) // possibly cv / ref qualified
        {
            std::get<std::decay_t<Component>>(components) = component;
        }
    };
    
        2
  •  2
  •   Passer By    7 年前

    使用 std::variant 为了实现灵活性和简单性的结合,可能会牺牲一些内存。

    template<typename... Components>
    class Entity final {
        using variant = std::variant<Components...>;
        std::vector<variant> components;
    
    public:
        template<typename T>
        void add(T&& t) {
            components.push_back(std::forward<T>(t));
        }
    };
    

    当组件的大小变化很大时,就会出现内存问题。假设一个是1字节,另一个是200字节,则 std::vector 将至少有200个字节大。

    另一个解决方案是 std::any .

    template<typename... Components>
    class Entity final {
        std::vector<std::any> components;
    
    public:
        template<typename T>
        void add(T&& t) {
            static_assert((std::is_same_v<Components, std::decay_t<T>> || ...));
            components.push_back(std::forward<T>(t));
        }
    };
    

    除了非常小的对象外,大多数堆上肯定有所有的东西,但不会出现上述问题 std::变量 .

    在这种情况下 std::任何 ,我们使用类型系统只是为了启用检查,而不是管理数据的布局。