std::to_underlying是C++23引入的专用函数,用于安全、精确地将enum class转换为其底层类型值,要求编译器支持C++23、枚举为作用域枚举且值为常量表达式。

std::to_underlying 是 C++23 引入的专用工具,专为将 enum class(强类型枚举)安全转为其底层整型值而设计。它比手动 static_cast 更清晰、更类型安全,且编译期可检查——但前提是你的编译器已支持 C++23 且启用了对应标准。
为什么不能直接用 static_cast?
虽然 static_cast<int>(MyEnum::Value)</int> 在绝大多数情况下能工作,但它绕过了类型系统约束,容易误用于非枚举类型,也缺乏语义表达力。更重要的是:当枚举底层类型不是 int(比如 enum class E : uint8_t),static_cast<int></int> 可能引发隐式截断或符号扩展,而 std::to_underlying 返回的是**精确的底层类型**,不做强制重解释。
- 它返回的是枚举定义时指定的底层类型(如
uint16_t),不是硬编码的int - 对非枚举类型调用会触发编译错误,而不是静默转换
- 在 constexpr 上下文中完全可用,适合元编程和模板推导
怎么用?必须满足哪些条件?
使用前需确认三点:
- 编译器支持 C++23(GCC 13+、Clang 16+、MSVC 19.35+;并启用
-std=c++23或等效选项) - 目标枚举必须是
enum class或enum struct(即作用域枚举),普通enum不允许调用 - 枚举值必须是常量表达式(即编译期可知),否则无法用于 constexpr 场景
基本用法:
enum class Color : uint8_t { Red = 1, Green = 2, Blue = 4 };<br>constexpr auto val = std::to_underlying(Color::Red); // 类型是 uint8_t,值是 1
立即学习“C++免费学习笔记(深入)”;
常见误用与编译错误
以下写法都会导致编译失败:
- 对非作用域枚举调用:
enum OldStyle { A }; std::to_underlying(A);→ 错误:not an enumeration type - 传入非常量表达式(如函数参数):
void f(Color c) { auto x = std::to_underlying(c); }→ 非 constexpr 上下文虽可能通过,但失去类型推导优势;若在 constexpr 函数中则报错 - 忘记包含头文件:
<utility></utility>—— C++23 中该函数定义在此头文件,不是<type_traits></type_traits>或<cstdint></cstdint>
典型错误信息:error: no matching function for call to 'to_underlying',往往是因为类型不匹配或标准未启用。
替代方案:C++20 及更早版本怎么办?
如果无法升级到 C++23,推荐封装一个轻量兼容函数:
template <typename E><br>constexpr std::underlying_type_t<E> to_underlying(E e) noexcept {<br> return static_cast<std::underlying_type_t<E>>(e);<br>}
这个实现复用了 std::underlying_type_t 确保类型精准,并保留 constexpr 属性。注意它仍要求 E 是枚举类型,否则 std::underlying_type_t 会 SFINAE 失败。
真正容易被忽略的是:即使你写了这个替代函数,也无法获得 C++23 版本的“编译期类型检查强化”——例如传入一个 int 假冒枚举值,它仍会静默转换成功。而原生 std::to_underlying 会直接拒绝。


















