C++23未提供原生编译期反射,当前依赖宏、编译器扩展或外部工具;C++26将通过P2320提案引入reflexpr等核心机制,支持字段/基类静态遍历与名称类型提取。

目前(截至C++23标准正式发布),C++ 语言本身尚未提供原生、完整的编译期反射(compile-time reflection)支持。所谓“C++23 reflection 提案”,实际指的是被 推迟到 C++26 的核心提案 P2320R0 — “Compile-time Reflection”,它并未进入 C++23 标准。因此,当前所有“C++ 编译期反射”能力均依赖于:编译器扩展、宏 + 模板元编程模拟 或 外部代码生成工具。
当前可行的“类反射”实现方式(C++20/23 环境)
在没有标准反射的前提下,主流实践围绕“字段枚举 + 类型提取”展开,目标是达成类似 for_each_field(obj, [](auto&& f) { /* ... */ }); 的效果:
-
基于宏的声明式注册:用户用宏(如
REFLECT_STRUCT(MyType, (int, x), (std::string, name)))显式列出成员,宏展开为特化模板、友元注入或 constexpr 数据表; -
借助 Clang 的
__reflect扩展(实验性):仅限特定 Clang 构建版本,非可移植方案,不推荐用于生产; -
利用 C++20
consteval+ 模板参数推导模拟:例如通过重载get_member_names返回() std::array,但字段访问仍需手动映射,无法真正自动遍历; -
外部工具链辅助(推荐用于大型项目):如 foonathan/compat、Outcome 中的反射片段,或自研基于 Clang LibTooling 的代码扫描器,生成
reflect_*.h头文件供编译期使用。
C++26 反射提案(P2320)的关键设计方向
虽然未进 C++23,但 P2320 已形成较稳定共识,核心能力包括:
-
统一反射实体(
reflexpr):类似reflexpr(MyClass)返回一个编译期常量对象,携带其结构信息; -
字段/函数/基类的静态遍历:通过
get_data_members_v、get_base_classes_v等元函数获取类型列表; -
名称与类型的编译期提取:如
get_name_v得到字符串字面量,get_type_v得到对应类型; -
不支持运行时动态发现:所有操作必须在
consteval函数中完成,无 RTTI 依赖,零运行时开销。
实用技巧:用 C++20 实现最小可行反射骨架
以下是一个轻量、可移植的字段名+类型的 constexpr 映射示例(无需宏,但需用户显式特化):
立即学习“C++免费学习笔记(深入)”;
templatestruct reflect; template <> struct reflect
{ static constexpr std::array names{"x", "y", "tag"}; static constexpr std::array types{typeid(int), typeid(double), typeid(std::string)}; };
再配合 std::tuple 和 std::apply,即可实现字段遍历与序列化逻辑。关键点在于:把“反射信息”当作用户定义的 constexpr 数据,而非语言自动推导的结果。
基本上就这些——标准反射仍在路上,但合理分层(声明式描述 + 元编程驱动 + 工具辅助)已能让多数序列化、调试、绑定场景落地。不必等待 C++26,现在就能写出清晰、可维护的“伪反射”系统。










