C++子类实现中解包元组调用可变参数模板函数的问题
解决ECS中解包Tuple调用可变参数成员函数的问题
C++17 简洁实现方案
直接使用std::apply解包tuple,结合lambda传递参数,代码简洁且可读性高:
#include <tuple> 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){ std::apply([this, delta_time](auto&... components) { this->process_values(delta_time, components...); }, c); } } };
核心逻辑:
std::apply自动将tuplec的所有元素解包为lambda的参数- lambda捕获当前对象指针
this和delta_time,直接调用子类实现的process_values - 自动推导的
auto&... components会完美匹配Ts&...的类型(包括带const修饰的组件,比如const rigid_body_component&)
C11/C14 兼容实现方案
如果需要兼容更早的C++标准,可借助索引序列手动解包tuple:
#include <tuple> #include <utility> 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; private: // 辅助函数:通过索引序列定位tuple元素并解包 template<std::size_t... Is> void process_tuple(float delta_time, component_types& c, std::index_sequence<Is...>) const { process_values(delta_time, std::get<Is>(c)...); } public: void update(float delta_time) const { auto component_view = registry.get_view<Ts...>(); for (auto& c : component_view){ // 生成与Ts数量匹配的索引序列,传递给辅助函数 process_tuple(delta_time, c, std::index_sequence_for<Ts...>{}); } } };
核心逻辑:
std::index_sequence_for<Ts...>生成包含0到sizeof...(Ts)-1的索引序列- 辅助函数
process_tuple通过std::get<Is>(c)取出tuple对应位置的元素,解包后传递给process_values
注意事项
- 确保包含必要头文件:
<tuple>(用于tuple操作)、<utility>(用于索引序列) - 如果
component_view返回的是const component_types&,需将循环变量改为const auto& c,同时调整辅助函数的参数为const component_types& c - 需保证
registry.get_view<Ts...>返回的可迭代对象,其元素类型与component_types完全匹配
内容的提问来源于stack exchange,提问作者matreska
相关产品推荐
相关产品推荐

