c++oding="utf-8" ?>
std::to_underlying是c++23新增函数,用于安全获取枚举底层值;需gcc 13+/clang 16+/msvc 19.35+并启用-std=c++23,否则需static_cast替代,且仅接受枚举值而非指针或引用。

std::to_underlying 是 C++23 新增的工具,不是所有编译器都支持
如果你在 g++ 或 clang++ 下编译失败,报错类似 ‘to_underlying’ is not a member of ‘std’,大概率是因为标准库还没跟上 C++23。GCC 13、Clang 16 起才开始提供该函数(且需显式启用 -std=c++23),MSVC 19.35+ 也支持,但旧版本(如 VS2022 17.4)仍不包含。
确认方式:先写一句 static_assert(__cpp_lib_to_underlying >= 202110L);,编译不过就别硬用——此时得手动转型:
enum class Color { Red = 1, Green = 2 };
Color c = Color::Green;
auto val = static_cast<:underlying_type_t>>(c); // 等价替代</:underlying_type_t>
std::to_underlying 只接受枚举类型,不能传指针或引用
常见误用是把变量地址或引用直接丢进去,比如 std::to_underlying(&e) 或 std::to_underlying(std::ref(e)),这会触发编译错误:no matching function for call to ‘to_underlying’。它只重载了枚举类型的值参数(T,非 T& 或 T*)。
- ✅ 正确:
std::to_underlying(Color::Red)、std::to_underlying(c) - ❌ 错误:
std::to_underlying(&c)、std::to_underlying(std::move(c))(虽然std::move后仍是值类别,但没必要,且易误导) - ⚠️ 注意:如果枚举是
constexpr,std::to_underlying也能用于常量表达式,比如模板非类型参数推导
底层类型不明确时,std::to_underlying 的结果依赖枚举定义
没显式指定底层类型的枚举(如 enum E { A, B };),其底层类型由编译器决定(通常是 int,但可能因值范围变化)。而 std::to_underlying 返回的就是那个实际底层类型,不是固定 int。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
这意味着:若你假设返回值可无损赋给 int16_t,但枚举实际底层是 long(比如含大值),就可能截断或触发警告。安全做法是用 auto 或显式写成 std::underlying_type_t<e></e>:
enum class Status : uint8_t { OK = 0, Err = 255 };
auto x = std::to_underlying(Status::Err); // x 是 uint8_t 类型,不是 int
和 static_cast 相比,std::to_underlying 没有运行时开销,但语义更清晰
两者生成的汇编完全一样(都是零成本抽象),区别纯在表达意图:static_cast 是通用强制转换,容易掩盖枚举意图;std::to_underlying 明确说“我要取底层整型值”,对代码可读性和静态分析友好。
尤其在模板中,它能避免 SFINAE 或概念约束时写一堆 std::is_enum_v + static_cast 组合:
template<typename e>
constexpr auto safe_value(E e) {
if constexpr (std::is_enum_v<e>)
return std::to_underlying(e);
else
return static_cast<long>(e);
}</long></e></typename>
真正容易被忽略的是:它不处理作用域外的枚举(即非 enum class 的 enum)——虽然标准允许,但部分早期实现(如 libc++ 15)对无作用域枚举支持不完整,建议优先用 enum class。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










