std::to_underlying是C++23新增的constexpr函数模板,专用于将枚举值安全转为其底层整数类型,仅接受枚举值(非类型名),不进行范围检查,与static_cast等价,需配合std::underlying_type_t分工使用。

std::to_underlying 是 C++23 新增的函数,专用于安全、类型明确地把枚举值转为其底层整数类型;它不是宏、不是模板别名,而是一个 constexpr 函数模板,必须传入枚举值(非类型、非类型名)。
std::to_underlying 只能传枚举值,不能传枚举类型名
常见错误是把它当 std::underlying_type 用,比如写 std::to_underlying<myenum></myenum> 或 std::to_underlying(Status)——这会直接编译失败,因为它的参数是值(E),不是类型(typename E)。
正确用法只有一种:传一个已定义好的枚举变量或字面量:
enum class Color : uint8_t { Red = 1 }; auto v = std::to_underlying(Color::Red); // ✅ v 类型是 uint8_tColor c = Color::Red; auto x = std::to_underlying(c); // ✅ 同样有效std::to_underlying(42); // ❌ 编译错误:42 不是枚举值std::to_underlying<color>; // ❌ 编译错误:不是函数调用语法</color>
std::to_underlying 不做范围检查,越界就是未定义行为
它只是“原样转发”枚举值到其底层类型,不校验是否溢出。一旦底层类型装不下,行为就不可预测。
立即学习“C++免费学习笔记(深入)”;
enum class Big : char { X = 300 }; auto x = std::to_underlying(Big::X); // ❌ UB:char 通常最大为 127- 这种问题在从网络/文件读取原始字节再构造枚举时极易发生,务必先用
static_cast检查范围,或用std::is_valid_enum(需自实现)兜底 - 它和
static_cast在安全性上完全等价,别误以为它是“更安全”的替代品
std::to_underlying 和 std::underlying_type_t 的关系与分工
两者互补,但用途完全不同:前者处理“值”,后者处理“类型”。混用会导致逻辑混乱。
-
std::underlying_type_t<color></color>是类型(如uint8_t),用于声明变量、模板参数、sizeof等 -
std::to_underlying(Color::Red)是值(如1),用于计算、序列化、日志输出等运行时场景 - 想封装通用转换函数?推荐这样写:
template<typename e> constexpr auto to_underlying(E e) { return static_cast<:underlying_type_t>>(e); }</:underlying_type_t></typename>—— 它比std::to_underlying更早可用(C++11 起),且可被旧编译器支持
最容易被忽略的一点:如果你的枚举是前向声明的(enum class E;),而定义在别处,std::to_underlying 无法实例化——因为底层类型不可知。这意味着它不能用于仅靠前向声明就能使用的接口设计中。


















