C++是否有内置机制可自动生成调用类所有成员同名函数/运算符的代码?
C++ 类成员批量调用原生实现方案
截至C23标准,C还没有完全内置的全功能反射机制直接实现任意类的成员自动遍历,但有多个比宏更安全、更易维护的原生语法方案可以实现需求,完全可以替代旧的复杂宏实现。
方案1:C++11及以上 手动显式成员列表(适用所有类类型,无第三方依赖)
这个方案对类没有聚合要求,即使成员是protected/private也可以使用,只需要在类内部定义一次成员列表即可,是兼容性最好的方案:
#include <tuple> #include <utility> // 通用批量调用Save的实现(C++17及以上支持折叠表达式) template<typename T, typename Stream> void BatchSave(T& obj, Stream& s) { std::apply([&](auto... member_ptr) { ((obj.*member_ptr).Save(s), ...); }, T::kReflectMembers); } // C++11兼容的实现(无法升级C++版本时使用) template<typename T, typename Stream> void BatchSaveCpp11(T& obj, Stream& s) { using swallow = int[]; (void)swallow{1, ((obj.*std::get<sizeof...(Is)>(T::kReflectMembers)).Save(s), 0)...}; }
业务类仅需添加一行成员列表定义即可:
class TYPE { protected: XTYPE A, B, C; // 仅需定义一次要遍历的成员列表,后续所有批量操作(Save/Load/比较/序列化等)都可复用 static constexpr auto kReflectMembers = std::make_tuple(&TYPE::A, &TYPE::B, &TYPE::C); public: void Save(stream s) { BatchSave(*this, s); } };
方案优势:
- 完全原生语法,无任何宏使用,类型安全,编译期会自动检查所有成员是否实现了对应方法
- 成员列表只需要定义一次,新增通用逻辑不需要重复罗列成员
- 不受类成员访问控制限制,只要在类内部定义成员列表即可
- 生成的二进制代码和手动逐行调用完全一致,无额外运行时开销
方案2:C++17及以上 无侵入式聚合反射(适用聚合类,无需修改类定义)
如果你的类是聚合类型(C17要求无用户声明构造函数、无虚函数、所有非静态成员都是public;C20放宽限制允许protected成员),可以直接用轻量纯头文件库Boost.PFR(又名Magic Get,不需要引入整个Boost库)实现完全无侵入的成员遍历,不需要在类内部加任何额外代码:
#include <boost/pfr.hpp> template<typename T, typename Stream> void BatchSaveAggregate(T& obj, Stream& s) { boost::pfr::for_each_field(obj, [&](auto& field) { field.Save(s); }); } // 业务类不需要任何修改 class TYPE { protected: XTYPE A, B, C; public: void Save(stream s) { BatchSaveAggregate(*this, s); } };
方案优势:
- 完全无侵入,不需要修改原有类结构
- 不需要手动维护成员列表,新增/删除成员时不需要调整任何代码,自动遍历所有成员
- 同样是编译期实现,无运行时开销
方案3:C++26 原生反射(未来标准)
目前正在推进的C++26标准已经纳入了静态反射提案,届时可以直接通过语言内置的反射接口遍历类的所有成员,不需要任何辅助库或者额外定义,完全满足原生语言机制的需求,目前GCC、Clang已经有实验性支持。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

