std::to_underlying是C++23新增函数,需启用-std=c++23且编译器支持(Clang 15+/GCC 13+/MSVC 19.35+),头文件为<utility>;C++20及更早版本须用static_cast<std::underlying_type_t<E>>(e)替代。

std::to_underlying 是 C++23 才加入的标准库函数
如果你编译失败,报错 ‘to_underlying’ is not a member of ‘std’,大概率是因为编译器还没启用 C++23 或标准库不支持。它不在 C++20 及更早版本中,不是“漏装头文件”能解决的问题。
- Clang 15+、GCC 13+、MSVC 19.35+(VS 2022 17.5+)才提供该函数,且需显式开启
-std=c++23(或-std=gnu++23) - 头文件是
<utility>,但即便包含也无法绕过语言标准限制 - 若无法升级标准,可用
static_cast<std::underlying_type_t<E>>(e)替代,效果等价但更啰嗦
std::to_underlying 只接受无作用域枚举(enum)和有作用域枚举(enum class)
它对枚举类型的底层类型不做假设,但要求参数必须是枚举值(不是指针、引用或整数),否则编译报错。
- 合法:
std::to_underlying(Color::red)、std::to_underlying(Status::ok) - 非法:
std::to_underlying(42)(不是枚举值)、std::to_underlying(&e)(取地址)、std::to_underlying(static_cast<int>(e))(已转为 int) - 注意:即使 enum class 底层是
unsigned char,std::to_underlying返回的仍是对应底层类型,不是固定为int
底层类型推导依赖枚举定义,不是运行时行为
std::to_underlying(e) 的返回类型由枚举声明时的 : T 显式指定,或由编译器按规则推导(如值范围决定用 int 还是 long long)。它不改变值,也不做截断或符号扩展——只是原样 reinterpret 为底层整型。
- 例如:
enum class E : uint8_t { a = 255 };→std::to_underlying(E::a)返回uint8_t类型的255,不是int - 若后续用在需要
int的上下文(如printf("%d", ...)),会隐式提升,但可能因符号性引发意外(比如uint8_t{255}提升为int{255}没问题,但int8_t{-1}提升后仍是-1) - 别假设返回值一定是
int;必要时显式static_cast<int>,尤其跨平台或做算术时
和传统 static_cast 相比,优势在于语义明确与模板友好
它本质是语法糖,但消除了手写 static_cast 时反复查 std::underlying_type_t 的麻烦,尤其在泛型代码里更安全。
立即学习“C++免费学习笔记(深入)”;
- 模板中写
std::to_underlying(e)即可,不用写static_cast<std::underlying_type_t<decltype(e)>>(e) - 编译器能更好识别意图,部分静态分析工具可据此检查枚举越界或未定义行为
- 但性能完全相同——生成的汇编指令和手工
static_cast一致,无额外开销 - 如果项目长期需兼容 C++20,建议封装一层:用
if constexpr (std::is_cpp23)分支,或直接用宏检测标准版本
std::to_underlying 结果后,下一步怎么用,得看你枚举当初是怎么定义的。


















