C++如何自动化为不同类型执行重复的DeserializeComponent反序列化代码?
实现方案
C++确实无法直接将类型存储到std::vector,但你可以通过类型擦除包装操作或者编译期类型列表遍历两种方案实现需求,全程不需要用到RTTI。
方案1:运行时动态注册(支持启动前预注册组件)
核心思路是把每个组件对应的反序列化操作包装成统一签名的可调用对象,存入容器统一调度,适合需要灵活增删注册组件的场景。
步骤1:定义公共注册表和注册接口
#include <vector> #include <functional> // 假设你用的json库是nlohmann/json,实体类型为Entity,根据实际场景替换即可 #include <nlohmann/json.hpp> using Entity = uint32_t; // 替换为你自己的实体类型 using DeserializeFunc = std::function<void(const nlohmann::json&, Entity)>; // 用函数静态变量规避静态初始化顺序问题 inline std::vector<DeserializeFunc>& GetComponentDeserializeRegistry() { static std::vector<DeserializeFunc> s_registry; return s_registry; } // 模板注册函数,每个组件类型实例化对应一个注册逻辑 template<typename TComponent> bool RegisterComponentForDeserialize() { GetComponentDeserializeRegistry().emplace_back([](const nlohmann::json& json, Entity e) { DeserializeComponent<TComponent>(json, e); }); return true; }
步骤2:全局预注册需要的组件
在任意全局作用域下添加以下代码,程序启动时会自动完成注册:
// 注册所有需要反序列化的组件 inline const bool g_regID = RegisterComponentForDeserialize<IDComponent>(); inline const bool g_regName = RegisterComponentForDeserialize<NameComponent>(); inline const bool g_regPointLight = RegisterComponentForDeserialize<PointLightComponent>(); // 新增组件只需要加一行注册代码即可
步骤3:遍历执行所有反序列化逻辑
需要反序列化时直接遍历注册表即可:
void DeserializeAllComponents(const nlohmann::json& json, Entity e) { for (const auto& func : GetComponentDeserializeRegistry()) { func(json, e); } }
方案2:编译期固定类型列表遍历(无任何运行时开销)
如果你的组件列表是固定的,不需要动态增删,直接用C++17折叠表达式实现编译期展开即可,连容器都不需要:
template<typename... TComponents> void DeserializeAllComponents(const nlohmann::json& json, Entity e) { // 折叠表达式会按顺序展开所有DeserializeComponent调用,完全等价于你手写的逐行调用 (DeserializeComponent<TComponents>(json, e), ...); } // 调用时传入所有需要的组件类型即可 void Test(const nlohmann::json& json, Entity e) { DeserializeAllComponents<IDComponent, NameComponent, PointLightComponent>(json, e); }
两种方案都完全规避了RTTI的使用:方案1通过函数擦除了类型差异,只保存统一的操作入口;方案2所有逻辑都在编译期完成展开,没有运行时类型判断逻辑。
内容的提问来源于stack exchange,提问作者Rid
相关产品推荐
相关产品推荐

