第2.16章: enum class
什么是 enum class
enum class(有作用域枚举)定义了一组有名字的常量,
它们是强类型的,并且带有作用域。
枚举值不会泄漏到外围作用域,也不会隐式转换为整数或其他枚举类型。
enum class Color { Red, Green, Blue };
// Declaration and comparison without leaking names
Color c{Color::Red};
bool is_red{c == Color::Red};
指定底层类型
你可以指定底层的存储类型。若省略,则默认为 int。
enum class Status : unsigned char { Ok, Warning, Error };
// Declaration using the underlying storage
Status s{Status::Error};
与底层整数类型之间的转换
enum class 不会隐式转换为整数。请使用显式转换:
- ::std::to_underlying(value):返回底层整数值。需要包含
<utility>头文件。 - static_cast<::std::underlying_type_t<T>>(value):转换为该枚举的底层类型。需要包含
<type_traits>头文件。
#include <utility> // ::std::to_underlying
#include <type_traits> // ::std::underlying_type_t
enum class ErrorCode { None, Minor, Major };
// To integer
auto v1{::std::to_underlying(ErrorCode::Major)};
auto v2{static_cast<::std::underlying_type_t<ErrorCode>>(ErrorCode::Major)};
// Back to enum
ErrorCode e1{static_cast<ErrorCode>(v1)};
ErrorCode e2{static_cast<ErrorCode>(v2)};
bool ok1{e1 == ErrorCode::Major};
bool ok2{e2 == ErrorCode::Major};
这些整数值可用于算术、位运算、存储或互操作。当你需要语义上的清晰时,再转换回枚举类型。
用 using enum 把枚举值引入作用域
通过 using enum,你可以把某个枚举的所有值引入当前作用域,从而无需限定即可使用它们。
enum class Color { Red, Green, Blue };
Color a{Color::Green};
// Bring all Color values into scope
using enum Color;
Color b{Blue}; // No need to write Color::Blue
bool is_green{a == Green};
请注意可读性。using enum 减少了冗长,但同时也隐藏了枚举名。
只在它明显提升清晰度的地方使用(例如局部作用域或简短的类 switch 逻辑)。
枚举的算术与位运算
进行算术与位运算时,请把枚举值转换为它们的底层整数类型。 显式地定义标志或掩码,然后用整数进行计算。
#include <utility>
enum class Permission : unsigned {
Read = 1u,
Write = 2u,
Execute = 4u
};
using enum Permission; // bring Read, Write, Execute into scope
// Build a mask from enum values via underlying integers
unsigned mask{::std::to_underlying(Read) | ::std::to_underlying(Write)};
// Test a flag
bool has_write{(mask & ::std::to_underlying(Write)) != 0u};
// Add a flag
mask |= ::std::to_underlying(Execute);
// Remove a flag
mask &= ~::std::to_underlying(Read);
// Store and restore from an integer
Permission p_exec{static_cast<Permission>(::std::to_underlying(Execute))};
bool is_exec{p_exec == Execute};
避免直接对枚举值做算术运算。始终在底层整数上操作,并在适当的地方转换回枚举。
要点
- 有作用域且强类型:
enum class防止名字泄漏和隐式转换。 - 底层类型:当存储大小或 ABI 重要时,请指定它。
- 显式整数转换:使用
::std::to_underlying或static_cast<::std::underlying_type_t<T>>;需要包含<utility>或<type_traits>。 - using enum:把枚举值引入作用域以减少冗长;请谨慎使用。
- 算术/位运算:在底层整数上操作;为清晰起见再转换回枚举。