繁体   English   中英

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

[英]How to create compile-time class fields using templates?

小背景和基本原理

我正在设计一个编译时ECS。 设计有其特定的细节-例如,会有各种各样的实体。 这意味着组件的总数可能会很高,而每个实体的组件数会很低(具有一些显而易见的,几乎在任何地方都存在的常见特征,例如SpriteBoundingBox

我的方法

我将实现以下接口:

/* 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 {};

但是,我不知道如何为各个Component类型创建句柄数据字段,甚至根本不可能。 谁能帮我或解释一下为什么行不通(或可能提出其他解决方案)?

只需使用std::tuple 注意, 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;
    }
};

使用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::any除了很小的对象外, std::any东西当然都具有堆上的所有内容,但不会遭受上述std::variant问题的困扰。

在使用std::any的情况下,我们仅使用类型系统来启用检查,而不是控制数据的布局。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM