C++20/23无标准编译期反射,仅支持std::is_same_v等类型关系推导;所谓“反射”实为误传,真正字段名、方法列表等能力需依赖宏或外部工具。

编译期反射在 C++20 里根本不存在
标准 C++ 目前(C++20 / C++23)没有编译期反射。所谓“C++ 编译期反射”是误传,或指代实验性提案、第三方库模拟、或对 std::is_same_v、decltype、std::declval 等已有机制的过度解读。真正能做的,只是在编译期推导类型关系、提取基础属性(如大小、对齐、是否可构造),而非获取字段名、方法列表、注解等完整运行时反射能力。
用 std::is_same_v 和 std::is_base_of_v 做最简类型判断
这是最常用、最可靠、零开销的“编译期类型信息”用法。它们不依赖任何宏或代码生成,直接由编译器求值,适用于 SFINAE、if constexpr 分支、约束概念(concepts)。
-
std::is_same_v判断T是否就是int,不是const int或int&(需先用std::remove_cvref_t归一化) -
std::is_base_of_v只对真实继承关系有效,对模板别名或类型擦除(如std::any)完全无效 - 避免在非模板上下文中硬写
std::is_same_v——编译器会直接报错或恒为false,失去编译期分支意义
用 constexpr 函数 + 模板特化模拟字段计数
有人想“反射出结构体有 3 个成员”,实际只能靠人工维护或宏生成。比如:
template<typename t> constexpr size_t field_count_v = 0; template constexpr size_t field_count_v<mystruct> = 3; </mystruct></typename>
这不算反射,是手动注册。真正危险的是用宏自动生成这类特化——一旦头文件包含顺序变化、或 MyStruct 定义在模板内部,特化就失效,且错误信息极难定位。
- 宏生成的代码不可调试,
gdb看不到字段名,IDE 无法跳转 - 每个新增结构体都要加一条特化,违背“写一次,到处用”的直觉
-
static_assert(field_count_v是唯一靠谱的兜底> 0, "forgot to specialize");
别碰 __reflect、__typeinfo 这类编译器扩展
MSVC 的 __reflect、Clang 的 __typeinfo(非标准)或 GCC 的 __builtin_types_compatible_p 都不稳定:版本一升级就变,跨平台项目基本没法用,且几乎不支持嵌套类型、模板参数展开、constexpr 上下文。
- 用
__reflect(MyStruct)获取字段名?它返回的是编译器内部字符串字面量,不能参与constexpr if分支 - 这些扩展不进标准,C++26 反射 TS(P0996)已被搁置,短期内不会落地
- 真要字段名,老实用
BOOST_PP宏或外部代码生成器(如reflexpr+ Python 脚本),但得接受构建链变重
编译期拿到字段名这件事,目前没有轻量、标准、可移植的解法。所有“一行实现反射”的示例,背后都藏着宏地狱、构建脚本或编译器后门。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











