[C++]现代C++语言核心特性解析 Chapter 14

强枚举类型(C++11C++17 C++20)

1 枚举类型的弊端

类型问题

虽然枚举类型存在一定的安全检查功能,一个枚举类型不允许分配到另外一种枚举类型,而且整型也无法隐式转换成枚举类型。但是枚举类型却可以隐式转换为整型,因为C++标准文档提到“枚举类型可以采用整型提升的方法转换成整型”。

作用域问题

枚举类型会把其内部的枚举标识符导出到枚举被定义的作用域。也是就说,我们使用枚举标识符的时候,可以跳过对于枚举类型的描述。

2 使用强枚举类型

C++11增加了强枚举类型,具有以下特性:

  • 枚举标识符属于强枚举类型的作用域。
  • 枚举标识符不会隐式转换为整型。
  • 能指定强枚举类型的底层类型,底层类型默认为int类型。

定义语法很简单,只需要在枚举定义的enum关键字之后加上class关键字就可以了。

1
2
3
4
5
6
7
#include <iostream>

enum class HighSchool {
student,
teacher,
principal
};

强枚举类型不仅实现起来非常简洁,而且还是POD类型。

我们可以在定义类型的时候使用:符号来指明其底层类型。利用它可以消除不同编译器带来的歧义

1
2
3
4
5
6
7
8
9
10
11
enum class E : unsigned int {
e1 = 1,
e2 = 2,
e3 = 0xfffffff0
};

int main()
{
bool b = e1 < e3;
std::cout << std::boolalpha << b << std::endl;
}

3 列表初始化有底层类型枚举对象

从C++17标准开始,对有底层类型的枚举类型对象可以直接使用列表初始化。

1
2
3
4
5
6
7
8
9
10
11
12
enum class Color {
Red,
Green,
Blue
};
int main()
{
Color c{ 5 }; // 编译成功
Color c1 = 5; // 编译失败
Color c2 = { 5 }; // 编译失败
Color c3(5); // 编译失败
}

C++11标准中对强枚举类型初始化做了严格限制,目的就是防止枚举类型的滥用。可是C++17又打破了这种严格的限制,动机是什么?

现在假设一个场景,我们需要一个新整数类型,该类型必须严格区别于其他整型,也就是说不能够和其他整型做隐式转换,显然使用typedef的方法是不行的。另外,虽然通过定义一个类的方法可以到达这个目的,但是这个方法需要编写大量的代码来重载运算符,也不是一个理想的方案。所以,C++的专家把目光投向了有底层类型的枚举类型,其特性几乎完美地符合以上要求,除了初始化整型值的时候需要用到强制类型转换。于是,C++17为有底层类型的枚举类型放宽了初始化的限制,让其支持列表初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
enum class Index : int {};

int main()
{
Index a{ 5 };
Index b{ 10 };
// a = 12;
// int c = b;
std::cout << "a < b is "
<< std::boolalpha
<< (a < b) << std::endl;
}

4 使用using打开强枚举类型

C++20标准扩展了using功能,它可以打开强枚举类型的命名空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const char* ColorToString(Color c)
{
switch (c)
{
using enum Color;
case Red: return "Red";
case Green: return "Green";
case Blue: return "Blue";
default:
return "none";
}
}

const char* ColorToString(Color c)
{
switch (c)
{
using Color::Red;
case Red: return "Red";
case Color::Green: return "Green";
case Color::Blue: return "Blue";
default:
return "none";
}
}

[C++]现代C++语言核心特性解析 Chapter 14
https://erlsrnby04.github.io/2024/11/01/C-现代C-语言核心特性解析-Chapter-14/
作者
ErlsrnBy04
发布于
2024年11月1日
许可协议