【发布时间】:2016-01-18 22:03:40
【问题描述】:
很抱歉这个问题的措辞含糊。我遇到了一个似乎应该可以解决的问题,但我的调查有点死胡同。简而言之,我想要一个包含从类 A 继承的所有类型的编译时列表。话虽如此,我将直接进入我面临的问题。
假设我有两种类型:实体和组件。
class Entity {
public:
entity_id id;
std::vector<component_id> components;
};
和
template<typename UnderlyingComponentType>
class Component {
public:
static std::vector<UnderlyingComponentType> components;
component_id id;
entity_id containingEntity;
}
简而言之,每个实体都包含多个不同类型的组件(例如 TextComponent、SoundComponent、WeightComponent)。然而,不是直接将这些组件作为字段包含,而是仅将它们的 ID 存储在实体中。这允许对相同类型的组件进行快速迭代,因为它们都在一个连续的向量中(例如,可以一次性遍历所有 DescriptionComponents)。同样,可以为任何给定实体检索给定类型的任何组件:
DescriptionComponent& decription = myEntity.getComponent<DescriptionComponent>()
// Can go to the DescriptionComponent's static vector, and look up the
// appropriate component given our entity's ID (matching it with the component's
// containingEntity ID.)
可以为删除或添加单个组件提供类似的功能。但是,当我想删除给定实体的 所有 组件时,我遇到了问题。因为组件存储在实体之外,所以没有一种简单的方法可以说“循环遍历您包含的组件并将它们全部删除”。相反,我们必须为我们包含的每种组件类型转到底层静态向量,并从那里删除。这是我撞到砖墙的地方。这里似乎有两种潜在的解决方案:
1.) 在每个实体中存储一个类型集合,这些类型映射到我们包含的所有组件类型的组件向量(例如entity.getComponentTypes == X<DescriptionComponent, SoundComponent>; 这里的缺点是每个实体的组件可以不断变化(我可以添加一个WeightComponent 在上述示例中的运行时)。因此,我不相信有办法根据运行时类型信息(如type_indexes 等)链接到编译时类型
2.) 生成实现组件的每种类型的编译时列表,然后在实体要求删除其所有组件时循环遍历它们all。例如,假设我们有一个实体e,它的ID 为123,并包含一个DescriptionComponent 和一个SoundComponent。我们仍然会有一个包含[DescriptionComponent, SoundComponent, WeightComponent] 的类型的编译时列表,并且我们会告诉每个组件的静态向量删除123 引用的任何组件。由于只有DescriptionComponent和SoundComponent向量有这些引用,所以只有这两个会删除组件,e的所有组件都会被删除。
上面的选项 2 似乎是更可行的选项:创建一个编译时类型列表。手动编写代码很容易:std::tuple<DescriptionComponent, SoundComponent, WeightComponent> 可以轻松存储并允许我根据需要遍历这些类型。但是,我最理想的是以编程方式生成这个列表的方法,这样如果我以后再添加一个NameComponent,我就不必更新任何其他代码:它当我从我的模板化 Component 类继承时应该自动管理。例如,
class NameComponent : public Component<NameComponent> {
//implementation details
}
//Now, my all-types list should contain [DescriptionComponent, SoundComponent,
// WeightComponent, NameComponent], and I didn't have to update any config.
我完全不确定上述是否可以在本地实现,但任何帮助或资源建议都是可行的。我在this StackOverflow question 看到了一个类似的问题,但它依赖于宏(据我了解,不要以相同的方式与模板交互)。同样,如果这看起来像是一个 A/B 问题,而像 type_index 地图这样的简单解决方案实际上会起作用,那么这种类型的批评也会受到欢迎!我确信我忽略了一些细节或措辞不佳,所以如果/何时需要更多信息,请随时告诉我。
【问题讨论】:
-
我相信boost::hana 可能有你需要的东西。虽然在 msvc 下不起作用,而且它是一个额外的依赖项 - 但您要解决的任务并不简单(直到将来我们有编译时反射)
-
感谢资源,我去看看,我听说过 boost::hana 的好消息。很高兴知道问题本身有一些复杂性:编译时反射将是天赐之物!
标签: c++ templates c++11 metaprogramming c++14