当前位置: 首页 > ai >正文

探索 C++23 std::to_underlying:枚举底层值获取的利器

文章目录

    • 引言
    • 基本概念
    • 作用
    • 使用示例
    • 与之前方法的对比
    • 在 C++23 中的意义
    • 总结

引言

在 C++ 的发展历程中,每一个新版本都带来了许多令人期待的新特性和改进,以提升代码的安全性、可读性和可维护性。C++23 作为其中的一个重要版本,也不例外。其中,std::to_underlying 这个工具函数便是 C++23 为开发者带来的一个实用礼物,它主要用于获取枚举(enum)的底层值。本文将深入探讨 std::to_underlying 的相关内容,包括其基本概念、作用、使用示例、与之前方法的对比以及在 C++23 中的意义。

基本概念

std::to_underlying 是 C++23 标准库中新增的一个实用工具函数,定义于头文件 <utility> 中。其函数原型如下:

emplate< class Enum >
constexpr std::underlying_type_t< Enum> to_underlying( Enum e ) noexcept ;

该函数的作用是将枚举类型转换为其底层类型,等价于 return static_cast<std::underlying_type_t<Enum>>(e);。这里的 Enum 是枚举类型,e 是要转换的枚举值,函数返回的是 Enum 的底层类型的整数值,从 e 转换而来。

作用

在实际编程中,我们经常会遇到需要将枚举值转换为其底层整数类型的情况。例如,当我们需要与一些无类型的 API 进行交互时,或者在进行日志记录、流操作等场景下,都可能需要获取枚举的底层值。在 std::to_underlying 出现之前,开发者通常会使用 static_cast 来完成这个转换,但这种方式存在一些问题。

使用 static_cast 进行枚举到其底层类型的转换,会使代码的可读性和可维护性变差。因为在代码中,static_cast 看起来就像普通的类型转换,很难快速识别出这是一个从强类型枚举到其底层值的转换。而且,当枚举类型的底层类型发生变化时(例如从有符号类型变为无符号类型),使用 static_cast 的代码可能会出现潜在的错误。而 std::to_underlying 的出现,正是为了解决这些问题,它提供了一种更安全、更清晰的方式来获取枚举的底层值。

使用示例

下面通过几个具体的示例来展示 std::to_underlying 的使用方法。

#include <cstdint>
#include <iomanip>
#include <iostream>
#include <type_traits>
#include <utility>// 示例 1:不同枚举类型的底层类型验证
enum class E1 : char { e };
static_assert(std::is_same_v<char, decltype(std::to_underlying(E1::e))>);enum struct E2 : long { e };
static_assert(std::is_same_v<long, decltype(std::to_underlying(E2::e))>);enum E3 : unsigned { e };
static_assert(std::is_same_v<unsigned, decltype(std::to_underlying(E3::e))>);// 示例 2:实际输出枚举的底层值
int main()
{enum class ColorMask : std::uint32_t{red = 0xFF, green = (red << 8), blue = (green << 8), alpha = (blue << 8)};std::cout << std::hex << std::uppercase << std::setfill('0')<< std::setw(8) << std::to_underlying(ColorMask::red) << '\n'<< std::setw(8) << std::to_underlying(ColorMask::green) << '\n'<< std::setw(8) << std::to_underlying(ColorMask::blue) << '\n'<< std::setw(8) << std::to_underlying(ColorMask::alpha) << '\n';// 编译错误示例,不能直接将枚举赋值给底层类型变量// std::underlying_type_t<ColorMask> x = ColorMask::alpha; // 正确示例,使用 std::to_underlying 进行转换[[maybe_unused]]std::underlying_type_t<ColorMask> y = std::to_underlying(ColorMask::alpha); return 0;
}

在上述代码中,示例 1 通过 static_assert 验证了不同枚举类型使用 std::to_underlying 转换后的底层类型是否正确。示例 2 则实际输出了 ColorMask 枚举的各个值的底层类型,并且展示了直接将枚举赋值给底层类型变量会导致编译错误,而使用 std::to_underlying 则可以正确进行转换。

与之前方法的对比

std::to_underlying 出现之前,开发者通常会使用 static_cast 来将枚举转换为其底层类型。例如:

enum class MyEnum : int { Value1, Value2 };
int underlyingValue = static_cast<int>(MyEnum::Value1);

这种方式虽然可以实现功能,但存在一些缺点。首先,代码的可读性较差,从 static_cast 的使用中很难一眼看出这是在进行枚举到其底层类型的转换。其次,当枚举的底层类型发生变化时,需要手动修改 static_cast 中的目标类型,否则可能会导致潜在的错误。

而使用 std::to_underlying 则可以避免这些问题。std::to_underlying 明确地表示了这是一个将枚举转换为其底层类型的操作,提高了代码的可读性。并且,无论枚举的底层类型如何变化,std::to_underlying 都能正确工作,无需手动修改代码。例如:

enum class MyEnum : int { Value1, Value2 };
int underlyingValue = std::to_underlying(MyEnum::Value1);

即使 MyEnum 的底层类型从 int 变为其他类型,上述代码仍然可以正常工作。

在 C++23 中的意义

std::to_underlying 的引入是 C++ 语言不断发展和完善的体现。它符合现代 C++ 注重代码安全性、可读性和可维护性的设计理念。在 C++23 中,std::to_underlying 作为标准库的一部分,为开发者提供了一个统一、规范的方式来处理枚举到其底层类型的转换。

随着 C++ 标准的不断演进,枚举类型在 C++ 中的应用也越来越广泛。从 C++11 引入的枚举类(enum class)解决了传统枚举的命名冲突和隐式转换问题,到 C++17 允许使用大括号初始化基础类型,再到 C++20 引入的 using enum 语法,枚举类型的功能不断得到增强。而 std::to_underlying 的出现,进一步完善了枚举类型的使用场景,使得开发者在处理枚举时更加方便和安全。

总结

std::to_underlying 是 C++23 为开发者带来的一个实用工具函数,它为获取枚举的底层值提供了一种更安全、更清晰的方式。通过使用 std::to_underlying,可以提高代码的可读性和可维护性,避免因枚举底层类型变化而带来的潜在错误。在实际开发中,当需要将枚举转换为其底层类型时,建议优先使用 std::to_underlying。相信随着 C++23 的逐渐普及,std::to_underlying 会在更多的项目中得到广泛应用。

http://www.xdnf.cn/news/3599.html

相关文章:

  • 单片机嵌入式字符流数据解析库
  • YOLOv11改进:利用RT-DETR主干网络PPHGNetV2助力轻量化目标检测
  • AVFormatContext 再分析二
  • (即插即用模块-Attention部分) 六十三、(2024 CVPR) MLKA 多尺度大核注意力
  • 计算机视觉与深度学习 | 什么是图像金字塔?
  • 如何用CSS实现HTML元素的旋转效果:从基础到高阶应用
  • SQL ROUND() 函数详解
  • MySQL基础关键_006_DQL(五)
  • 数智图书馆的信息组织革命:AI变革下的新秩序
  • Spring 事务的底层原理常见陷阱
  • Fabrice Bellard(个人网站:‌bellard.org‌)介绍
  • ad 多通道设计中出现的相关问题
  • AWS上构建基于自然语言和LINDO API的线性规划与非线性规划的优化计算系统
  • MCP 探索:MCP 集成的相关网站 Smithery、PulseMCP 等
  • Java面试趣事:从死循环到分段锁
  • Lua 基础 API与 辅助库函数 中关于创建的方法用法
  • 基于STM32的智能摇头风扇设计(WIFI+语音控制)
  • CGAL:最小包围圆
  • 共铸价值:RWA 联合曲线价值模型,撬动现实资产生态
  • 基于机器学习的心脏病数据分析与可视化(百度智能云千帆AI+DeepSeek人工智能+机器学习)健康预测、风险评估与数据可视化 健康管理平台 数据分析与处理
  • k8s 探针
  • 基于ArduinoIDE的任意型号单片机 + GPS北斗BDS卫星定位
  • 基于「骑手外卖系统」串联7大设计原则
  • 【Hot 100】 146. LRU 缓存
  • Three.js在vue中的使用(二)-加载、控制
  • 【ICMP协议深度解析】从网络诊断到安全实践
  • Mysql常用语句汇总
  • centos7.0无法安装php8.2/8.3
  • ROS2学习笔记|创建工作空间并打印文件内容
  • 视频编解码学习二之颜色科学