[C++] enum 以及 enum class 简单用法

C语言风格枚举类型 enum


这是一个enum类型

enum LogType {OK,Info,Error
};

可以像这样指定enum的基础类型(默认类型是int),用英文来说就是underlying type

enum LogType : unsigned int {OK,Info,Error
};

继续升级,指定每个枚举元素具体的值

enum LogType : unsigned int {OK = 0x00,Info = 0x01,Error = 0x02
};

经典位掩码,即Bitmask写法

enum WindowFlags : unsigned int {None = 0x0000,NoMove = 0x0001,NoResize = 0x0002,NoSavedSettings = 0x0004
};
auto MySettings = NoMove | NoResize;

但是enum本质上其实是无范围枚举,即unscoped enumeration,很容易就会发现命名冲突问题

enum LogType {OK,Info,Error
}; // OKenum StatusCode {OK,Forbidden
}; // OK?auto res = LogType::OK; // Compiler doesn't know which OK to use even using :: to specify

想要解决这个问题并不难,我们可以外面套一层struct或者class

struct LogType {enum {OK,Info,Error};
};class StatusCode {enum {OK,Forbidden};
};auto res = LogType::OK; // OK!

但是这样似乎不太优雅,尤其是我们想将enum作为函数返回值的时候

struct StatusCode {enum {OK,Forbidden};
};StatusCode foobar() {return StatusCode::OK; // Hey, don't do this!
};

C++风格枚举类型 enum class

为了解决以上种种问题,C++引入了enum class,这是一种范围枚举,即scoped enumeration,不存在命名冲突
用法和enum相似,无非就是在后面添加了一个struct或者class(等效)

enum struct LogType {OK,Info,Error
};enum class StatusCode {OK,Forbidden
};

我们也可以像enum一样把enum class类型作为函数返回值(可以把它看作是一个类)

enum class StatusCode {OK,Forbidden
};StatusCode foobar() {return StatusCode::OK;
};

值得注意的是,enum class并不支持隐式类型转换,即implicit type conversion
因此,enum class也并不能像enum那样直接进行位运算

enum class WindowFlags : unsigned int {None = 0x0000,NoMove = 0x0001,NoResize = 0x0002,NoSavedSettings = 0x0004
};WindowFlags foobar() {return WindowFlags::None;
};
if (!foobar())exit(EXIT_FAILURE); // g++: expression must have bool type (or be convertible to bool)
auto MySettings = NoMove | NoResize; // g++: no operator "|" matches these operands
auto MySettings = static_cast<WindowFlags> (static_cast<unsigned int> (WindowFlags::NoMove) | static_cast<unsigned int> (WindowFlags::NoResize)); // OK

显示类型转换,即explicit type conversion似乎过于臃肿,但是我们可以重载一下enum class相关的operator,以下模板放在我们的enum class的命名空间内即可(具体细节此处不赘述,请自行查阅std::enable_if_t, std::is_enum_v)

template <typename enum_type, typename cast_type = std::size_t>
constexpr std::enable_if_t<std::is_enum_v<enum_type>, enum_type> operator& (enum_type x, enum_type y) {return static_cast<enum_type>(static_cast<cast_type> (x) & static_cast<cast_type> (y));
}template <typename enum_type, typename cast_type = std::size_t>
constexpr std::enable_if_t<std::is_enum_v<enum_type>, enum_type> operator| (enum_type x, enum_type y) {return static_cast<enum_type>(static_cast<cast_type> (x) | static_cast<cast_type> (y));
}template <typename enum_type, typename cast_type = std::size_t>
constexpr std::enable_if_t<std::is_enum_v<enum_type>, enum_type> operator^ (enum_type x, enum_type y) {return static_cast<enum_type>(static_cast<cast_type> (x) ^ static_cast<cast_type> (y));
}template <typename enum_type, typename cast_type = std::size_t>
constexpr std::enable_if_t<std::is_enum_v<enum_type>, enum_type> operator~ (enum_type x) {return static_cast <enum_type> (~static_cast<cast_type> (x));
}template <typename enum_type, typename cast_type = std::size_t>
constexpr std::enable_if_t<std::is_enum_v<enum_type>, enum_type> operator&= (enum_type &x, enum_type y) {x = x & y;return x;
}template <typename enum_type, typename cast_type = std::size_t>
constexpr std::enable_if_t<std::is_enum_v<enum_type>, enum_type> operator|= (enum_type &x, enum_type y) {x = x | y;return x;
}template <typename enum_type, typename cast_type = std::size_t>
constexpr std::enable_if_t<std::is_enum_v<enum_type>, enum_type> operator^= (enum_type &x, enum_type y) {x = x ^ y;return x;
}

enum class严格意义上来说并不是一个常规意义上的class,所以无法通过重载自动转换为bool类型,但是我们可以手写一个any函数来判断位掩码

template <typename enum_type, typename cast_type = std::size_t>
constexpr std::enable_if_t<std::is_enum_v<enum_type>, bool> any(enum_type x) {return static_cast<cast_type> (x) == 0;
};

简单样例(已载入上述模板)

enum class WindowFlags : unsigned int {None = 0x0000,NoMove = 0x0001,NoResize = 0x0002,NoSavedSettings = 0x0004
};auto MySettings = WindowFlags::NoMove | WindowFlags::NoResize;if (any(MySettings)) { // To check if any flags are set/* do something */
}

参考链接

cppreference.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/25929.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux--多进程开发(5)--进程间通信(IPC)、linux间通信的方式、管道

进程间通讯概念 每两个进程之间都是独立的资源分配单元&#xff0c;不同进程之间不能直接访问另一个进程的资源。 但不同的进程需要进行信息的交互和状态的传递等&#xff0c;因此需要进程间通信&#xff08;IPC,inter processes cimmunication) 进程通信的目的&#xff1a; …

Uniapp开发微信小程序插件的一些心得

一、uniapp 开发微信小程序框架搭建 1. 通过 vue-cli 创建 uni-ap // nodejs使用18以上的版本 nvm use 18.14.1 // 安装vue-cli npm install -g vue/cli4 // 选择默认模版 vue create -p dcloudio/uni-preset-vue plugindemo // 运行 uniapp2wxpack-cli npx uniapp2wxpack --…

RabbitMQ 的介绍与使用

一. 简介 1> 什么是MQ 消息队列&#xff08;Message Queue&#xff0c;简称MQ&#xff09;&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO先入先出&#xff0c;只不过队列中存放的内容是message而已。 其主要用途&#xff1a;不同进程Process/线程T…

对比Grok3 普通账户与 30 美元 Super 账户:默认模式、Think 和 DeepSearch 次数限制以及如何升级

面对这个马斯克旗下的"最聪明"的人工智能&#xff0c;很多人都不知道他们的基本模式&#xff0c;本期将从几个方面开始说明&#xff1a; Grok3的背景与功能 账户类型及其详细背景 使用限制 使用限制对比表 如何充值使用 Super 账户 纯干货&#xff0c;带你了解…

【含文档+PPT+源码】基于过滤协同算法的旅游推荐管理系统设计与实现

项目介绍 本课程演示的是一款基于过滤协同算法的旅游推荐管理系统设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系…

牛客NC288803 和+和

​import java.util.Comparator;import java.util.PriorityQueue;import java.util.Scanner;​public class Main {public static void main(String[] args) {// 创建Scanner对象用于读取输入Scanner sc new Scanner(System.in);// 读取两个整数n和m&#xff0c;分别表示数组的…

【uniapp原生】实时记录接口请求延迟,并生成写入文件到安卓设备

在开发实时数据监控应用时&#xff0c;记录接口请求的延迟对于性能分析和用户体验优化至关重要。本文将基于 UniApp 框架&#xff0c;介绍如何实现一个实时记录接口请求延迟的功能&#xff0c;并深入解析相关代码的实现细节。 前期准备&必要的理解 1. 功能概述 该功能的…

DeepSeek能画流程图吗?分享一种我正在使用的DeepSeek画流程图教程

‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​​​‌​‌​‍‌​​‌​​‌​‍‌​‌‌‌‌​​‍‌​‌​‌‌​​‍‌​​​‌‌‌‌‍‌​‌‌​‌‌‌‍‌‌​​‌​‌​‍‌​​‌‌​‌‌‍‌​​​‌​‌​‍‌​‌‌‌​‌‌‍‌‌​​‌‌‌‌‍‌​‌‌‌​​​‍‌…

基于Electron的应用程序安全测试基础 — 提取和分析.asar文件的案例研究

目录&#xff1a; 4.4. 案例研究 4.4.2. 情况描述 4.4.3. 信息收集 4.4.3.2. 检查隐藏目录&#xff08;点目录&#xff09;的可能性 4.4.3.3. 使用 DB Browser for SQLite 打开 .db 文件 4.4.3.4. 寻找加密算法 4.4.3.5. 找到加密算法 4.4.3.6. 理解加密流程 4.4.3.7. 找到“Ke…

代码随想录算法训练day64---图论系列8《拓扑排序dijkstra(朴素版)》

代码随想录算法训练 —day64 文章目录 代码随想录算法训练前言一、53. 117. 软件构建—拓扑排序二、47. 参加科学大会---dijkstra&#xff08;朴素版&#xff09;总结 前言 今天是算法营的第64天&#xff0c;希望自己能够坚持下来&#xff01; 今天继续图论part&#xff01;今…

WPF中对滚动条进行平滑滚动

有时候我们在动态添加内容时&#xff0c;需要将滚动条滚动到指定内容处。 一般我们会调用ScrollViewer的ScrollToVerticalOffset&#xff08;垂直方向&#xff09;函数和ScrollToHorizontalOffset&#xff08;水平方向&#xff09;函数来控制滚动条滚动到指定位置。 正常滚动效…

Python 课堂点名桌面小程序

一、场景分析 闲来无事&#xff0c;老婆说叫我开发一个课堂点名桌面小程序&#xff0c;给她在课堂随机点名学生问问题。 人生苦短&#xff0c;那就用 Python 给她写一个吧。 二、依赖安装 因为要用到 excel&#xff0c;所以安装两个依赖&#xff1a; pip install openpyxl…

设计模式——过滤器模式在 Spring 中的实践

设计模式——过滤器模式在 Spring 中的实践 基础介绍模块介绍简单实现业务落地额外问题 基础介绍 过滤器模式&#xff08;Filter Pattern&#xff09;&#xff0c;也称为标准模式&#xff08;Criteria Pattern&#xff09;&#xff0c;是结构型设计模式之一&#xff0c;旨在通…

Linux网络 数据链路层

在Linux网络中&#xff0c;数据链路层位于物理层之上&#xff0c;网络层之下&#xff0c;其主要职责是将网络层的IP数据包封装成帧&#xff0c;并通过物理链路发送到目标设备。同时&#xff0c;它还负责接收来自物理层的帧&#xff0c;并将其解封装为数据包&#xff0c;传递给网…

Java 调试模式下 Redisson 看门狗失效

一、场景分析 前几天在做分布式锁测试&#xff1a; 在调试模式下&#xff0c;lock.lock() 之后打上断点&#xff0c;想测试一下在当前线程放弃锁之前&#xff0c;别的线程能否获取得到锁。 发现调试模式下&#xff0c;看门狗机制失效了&#xff0c;Redis 上 30 秒后&#xff0…

ktransformers 上的 DeepSeek-R1 671B open-webui

ktransformers 上的 DeepSeek-R1 671B open-webui 一、下载GGUF模型1. 创建目录2. 魔塔下载 DeepSeek-R1-Q4_K_M3. 安装显卡驱动和cuda4. 显卡 NVIDIA GeForce RTX 4090 二、安装ktransformers1. 安装依赖2. 安装uv工具链3. 下载源码4. 创建python虚拟环境 三、编译ktransforme…

线性模型 - 支持向量机

支持向量机&#xff08;SVM&#xff09;是一种用于分类&#xff08;和回归&#xff09;的监督学习算法&#xff0c;其主要目标是找到一个最佳决策超平面&#xff0c;将数据点分为不同的类别&#xff0c;并且使得分类边界与最近的数据点之间的间隔&#xff08;margin&#xff09…

html中的元素(2)

在用块级元素完成网页的组织和布局以后&#xff0c;要为其中的每一个小区块添加内容&#xff0c;就需要用到行内元素&#xff1a; 1.字体样式元素 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>HTML5 保留的文本格式元…

Pytorch中的主要函数

目录 一、torch.manual_seed(seed)二、torch.cuda.manual_seed(seed)三、torch.rand(*size, outNone, dtypeNone, layouttorch.strided, deviceNone, requires_gradFalse)四、给大家写一个常用的自动选择电脑cuda 或者cpu 的小技巧五、torch.version.cuda&#xff1b;torch.bac…

php特性

文章目录 函数特性匹配数组报错进制转换绕过正则表达式匹配换行绝对路径绕过 弱类型语言隐式转换核心概念转换规则 运算符优先级 函数特性 匹配数组报错 以此为例&#xff0c;如果传入参数是一个数组&#xff0c;则preg_match()函数报错返回0&#xff0c;完成绕过&#xff0c;…