[英]Unpacking a tuple to call a function templated with variadic arguments in a subclass implementation (C++)
I am in the midst of implementing an Entity Component System .我正在实施Entity Component System 。 I am running into issues when attempting to call a function templated with variadic arguments:尝试调用以可变参数 arguments 为模板的 function 时遇到问题:
template <typename... Ts>
struct engine_system : engine_system_base<Ts>... {
using component_types = std::tuple<Ts...>;
// subclass implements this
virtual void process_values(float delta_time, Ts&... ts) const = 0;
void update(float delta_time) const {
auto component_view = registry.get_view<Ts...>();
for (component_types& c : component_view){
process_values(delta_time, ?????); // issue
}
}
};
The engine_system_base
takes care of registering T
for each type in Ts
. engine_system_base
负责为Ts
中的每种类型注册T
。 On update
each system implementation is supposed to retrieve all necessary components from the registry.在update
时,每个系统实现都应该从注册表中检索所有必要的组件。 I am unfortunately not sure how I can unpack the component_types
instance to correctly call a subclass implementation.不幸的是,我不确定如何解压缩component_types
实例以正确调用子类实现。
Here is a full example (registry omitted):这是一个完整的示例(省略注册表):
// components are just "plain old data"
struct vec3 {
float x, y, z;
};
struct transform_component {
vec3 position, rotation, scale;
};
struct rigid_body_component {
vec3 velocity, acceleration;
};
Components store state and have no behavior.组件存储 state 并且没有任何行为。 Systems implement behavior based on Components.系统基于组件实现行为。
// internal systems
template <typename T>
struct engine_system_base {
engine_system_base() { /* register T for system in registry */ };
virtual ~engine_system_base() = default;
};
template <typename... Ts>
struct engine_system : engine_system_base<Ts>...{
using component_types = std::tuple<Ts...>;
virtual void process_values(float delta_time, Ts&... ts) const = 0;
void update(float delta_time) const {
auto component_view = registry.get_view<Ts...>();
for (auto& c : component_view){
process_values(delta_time, ?????); // issue
}
}
};
engine_system_base
registers T
for a subclass implementation. engine_system_base
为子类实现注册T
engine_system
uses engine_system_base
as a variadic base to register each T
in Ts
with the registry (omitted). engine_system
使用engine_system_base
作为可变参数基,将Ts
中的每个T
注册到注册表中(省略)。 Afterwards a system can be implemented as such:之后可以这样实现系统:
struct move_system : engine_system<transform_component, const rigid_body_component> {
void process_values(float delta_time, transform_component& tc, const rigid_body_component& rb) const final {
tc.position += rb.velocity * delta_time;
}
};
The move_system
can then be used to translate all entities, which are comprised of a transform_component
and rigid_body_component
.然后可以使用move_system
翻译所有实体,这些实体由transform_component
和rigid_body_component
。
int main() {
move_system ms{};
ms.update(0.016);
return 0;
}
In my first implementation I defined void update(float delta_time) const
individually for each system implementation, which works but duplicates the same exact implementation and only differs in by explicitly defining Ts...
for each subclass.在我的第一个实现中,我为每个系统实现单独定义了void update(float delta_time) const
,它可以工作但重复相同的确切实现,只是通过为每个子类显式定义Ts...
而有所不同。 Unfortunately I am running into aforementioned issue when attempting to refactor this logic into engine_system
.不幸的是,我在尝试将此逻辑重构为engine_system
时遇到了上述问题。
Replace ?????
换?????
with std::get<Ts>(c)...
assuming that each T
in Ts
is unique.使用std::get<Ts>(c)...
假设Ts
中的每个T
都是唯一的。
In case you have non-unique Ts
, as mentioned in comments, you can use a std::index_sequence
:如果您有非唯一的Ts
,如评论中所述,您可以使用std::index_sequence
:
[&]<auto... Is>(std::index_sequence<Is...>) {
process_values(delta_time, std::get<Is>(c)...);
}(std::index_sequence_for<Ts...>{});
Assuming component_view
type is component_types
, std::apply
might help:假设component_view
类型是component_types
, std::apply
可能会有所帮助:
void update(float delta_time) const {
auto component_view = registry.get_view<Ts...>();
for (auto& c : component_view){
std::apply([&](auto&... args){ process_values(delta_time, args...); }, c);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.