商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C++ std::to_underlying用法 _ 枚举转底层整数类型技巧【干货】

C++ std::to_underlying用法 _ 枚举转底层整数类型技巧【干货】

  发布于2026-07-17 阅读(0)

扫一扫,手机访问

聊一聊C++23里一个很实用的工具——std::to_underlying。它专门用来把枚举值安全、类型明确地转成它底层的整数类型。注意,它是一个constexpr函数模板,不是宏,也不是模板别名。使用时必须传进来的是枚举值,而不是枚举类型或者类型名。废话不多说,直接切正题。

最常踩的坑是什么?就是把它当std::underlying_type用。比如写成std::to_underlying或者std::to_underlying(Status),都会直接编译失败。为什么?因为它的参数是一个(参数类型是 E),不是类型(不是 typename E)。

正确的用法只有一种:传一个已经定义好的枚举变量或者字面量。看几个例子就明白了:

  • enum class Color : uint8_t { Red = 1 }; 然后 auto v = std::to_underlying(Color::Red); —— 这个 v 的类型就是 uint8_t,没问题。
  • 如果有 Color c = Color::Red;,那么 auto x = std::to_underlying(c); 同样有效。
  • 反过来,std::to_underlying(42); 会编译错误,因为42不是枚举值。
  • std::to_underlying; 也是错的,语法根本就不对。

但千万别误会,它虽然叫“安全转换”,实际上并不做任何范围检查。它只是原封不动地把枚举值转发到它的底层类型,不会校验是否溢出。一旦底层类型装不下你塞进去的值,行为就是未定义的。

具体来说:

  • 比如 enum class Big : char { X = 300 };,然后 auto x = std::to_underlying(Big::X); —— 这里 char 通常最大只能到127,所以结果是未定义行为(UB)。
  • 这种问题在从网络或者文件里读取原始字节再构造枚举时特别容易遇到。实战中,建议先用 static_cast 检查一下范围,或者自己实现一个 std::is_valid_enum 来兜底。
  • 说白了,std::to_underlying 在安全性上跟 static_cast 完全等价,别以为它是更安全的替代品。

说到这,就不得不提一下它和 std::underlying_type_t 的关系。这两者分工明确,互不替代:一个处理值,一个处理类型。混着用就容易逻辑混乱。

  • std::underlying_type_t 得到的是类型(比如 uint8_t),用来声明变量、做模板参数、算 sizeof 什么的。
  • std::to_underlying(Color::Red) 得到的是值(比如 1),用在计算、序列化、日志输出这些需要实际数值的场景。
  • 如果想封装一个通用的转换函数,推荐这样写:template constexpr auto to_underlying(E e) { return static_cast>(e); }。这个写法从C++11就能用,旧编译器也支持,比 std::to_underlying 更早可用。

最后提醒一个最容易忽略的点:如果你的枚举是前向声明的——比如 enum class E;,而定义在别处——那么 std::to_underlying 没法实例化,因为底层类型未知。这意味着它不能用在那种只靠前向声明就能用的接口设计里。这点在实际编码中很容易翻车,得留个心眼。

本文转载于:https://www.php.cn/faq/2318557.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注