在C++11引入强类型枚举(enum class)之后,枚举类型的类型安全性得到了很大提升,但是强类型枚举无法直接隐式转换为整数类型,过去要获取其底层值往往需要手动类型转换,不仅繁琐还容易引入错误。C++23标准中新增的std::to_underlying函数专门解决了这个问题,让枚举底层值的获取变得简单安全。

什么是std::to_underlying
std::to_underlying是C++23标准库
#include <utility>
#include <type_traits>
template <typename Enum>
constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept {
return static_cast<std::underlying_type_t<Enum>>(e);
}
可以看到它的实现本质就是对枚举值做static_cast转换,但是封装之后使用起来更加直观,也避免了手动写转换逻辑可能出现的类型错误。
std::to_underlying的基本用法
使用std::to_underlying非常简单,只需要包含对应的头文件,然后传入强类型枚举的实例即可,下面是基础的示例代码:
#include <iostream>
#include <utility> // 包含std::to_underlying
// 定义一个强类型枚举
enum class Color : uint8_t {
Red = 1,
Green = 2,
Blue = 3
};
int main() {
Color c = Color::Green;
// 获取枚举的底层值
auto underlying_val = std::to_underlying(c);
std::cout << "枚举底层值: " << static_cast<int>(underlying_val) << std::endl;
// 输出:枚举底层值: 2
return 0;
}
在这个例子中,我们定义了底层类型为uint8_t的强类型枚举Color,使用std::to_underlying直接获取了Color::Green对应的底层值2,不需要手动指定转换的目标类型,减少了出错的可能。
std::to_underlying的优势
- 类型安全:不需要手动写static_cast转换,避免写错目标类型导致的未定义行为。
- 代码简洁:一行代码就能完成转换,比手动转换的可读性更高。
- 通用性强:可以适配所有枚举类型,不管底层类型是什么,不需要针对不同的枚举写不同的转换逻辑。
C++23强类型枚举操作技巧
1. 结合范围for循环遍历枚举值
强类型枚举本身不支持直接遍历,但是可以结合底层值和std::to_underlying实现简单的遍历逻辑:
#include <iostream>
#include <utility>
enum class Weekday : int {
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7
};
int main() {
// 遍历枚举值,假设枚举值是连续的
for (int i = std::to_underlying(Weekday::Monday); i <= std::to_underlying(Weekday::Sunday); ++i) {
Weekday day = static_cast<Weekday>(i);
std::cout << "当前枚举值: " << i << std::endl;
}
return 0;
}
2. 枚举值的位运算操作
如果强类型枚举的底层类型是整数,并且需要支持位运算,可以结合std::to_underlying实现:
#include <iostream>
#include <utility>
enum class Permission : uint32_t {
Read = 1 << 0,
Write = 1 << 1,
Execute = 1 << 2
};
// 检查是否有写权限
bool has_write_permission(Permission p) {
return (std::to_underlying(p) & std::to_underlying(Permission::Write)) != 0;
}
int main() {
Permission p = static_cast<Permission>(std::to_underlying(Permission::Read) | std::to_underlying(Permission::Write));
std::cout << "是否有写权限: " << (has_write_permission(p) ? "是" : "否") << std::endl;
return 0;
}
3. 枚举与字符串的映射转换
在实际开发中经常需要枚举和字符串互相转换,可以结合std::to_underlying做映射表的索引:
#include <iostream>
#include <string>
#include <utility>
#include <array>
enum class Status : int {
Success = 0,
Failed = 1,
Pending = 2
};
// 枚举到字符串的映射表
constexpr std::array<std::string, 3> status_str = {"成功", "失败", "处理中"};
std::string status_to_string(Status s) {
int idx = std::to_underlying(s);
if (idx >= 0 && idx < status_str.size()) {
return status_str[idx];
}
return "未知状态";
}
int main() {
Status s = Status::Pending;
std::cout << "状态字符串: " << status_to_string(s) << std::endl;
return 0;
}
注意事项
- std::to_underlying是C++23新增的特性,使用的时候需要确保编译器支持C++23标准,比如GCC 13+、Clang 16+版本都支持该函数。
- 如果枚举的底层值不是连续的,使用std::to_underlying做遍历的时候需要额外处理越界的情况,避免访问到无效的枚举值。
- 不要对无效的枚举值使用std::to_underlying,虽然函数本身不会报错,但是得到的底层值没有实际意义。
总的来说,std::to_underlying是C++23中一个非常实用的小特性,它简化了强类型枚举的底层值转换流程,配合其他枚举操作技巧,可以让强类型枚举的使用更加灵活高效,同时保持类型安全的优势。
std::to_underlyingC++23强类型枚举枚举转换修改时间:2026-07-23 10:54:30