C++ 的枚举 enum,用来在有限的范围定义明确命名的常量,通常值是整数类型。每个枚举项都与一个底层类型常量值对应,如果未指明,第一项为 0,其他项均为前一项 +1。
enum Color {
blue, // 0
green, // 1
red = 6,
gray, // 7
};
有两种风格的枚举型别,C++98 风格的枚举型别和 C++11 风格的型别,两者有很大区别,通常来说后者更有优势。
C++98:
enum Color {
}
C++11:
enum class Color {
}
- 前者的枚举量的访问范围不只在枚举型别中,包含该枚举类型的地方都被包括,被称为不限范围的枚举型别;后者加了 class,是限定范围的枚举型别,也被称为枚举类。
- 不限范围枚举型别的枚举量会隐式转换到整数型别,从而可以转换到浮点型别。限定范围的枚举型别则不会隐式转换,如果需要采用强制转换的方式。
- 两者在 C++11 中都可以进行前置声明,但是前者需要编译器选择一个整数型别作为其底层型别,通常会为枚举型别采用足够表示枚举量值的最小底层型别(有时编译器会用空间换时间,这意味着可能不会采用足够表示的最小底层类型)。限定作用域的枚举型别的底层型别是已知的,而不限定作用域的枚举型别是供指定的。
- 底层型别的指定可以在枚举型别声明和定义中指定,限定作用域的底层型别默认是 int
#include <iostream>
using namespace std;
enum class Color;
// {
// blue,
// green,
// red = 6,
// gray,
// };
int main(int argc, char* argv[]) {
bool is_int_type = std::is_same<int,
typename std::underlying_type<Color>::type>::value;
if (is_int_type) {
std::cout << "int type\n";
}
return 0;
}
不管限定作用域与否,都可以使用“:”指定方式指定底层型别:
enum class Color: long long;
- 当引用 C++11 中的 std::tuple 型别的各个作用域时,前者比较适用。
对于单纯的 tuple 在外部不便得知每一项的信息,
#include <iostream>
#include <tuple>
using namespace std;
// enum class Color {
// blue,
// green,
// red = 6,
// gray,
// };
int main(int argc, char* argv[]) {
using Color = std::tuple<char, int, double>;
Color color{'a', 6, 2.33f};
auto b = std::get<2>(color);
std::cout << b << "\n";
return 0;
}
而采用不限范围的枚举型别则比较适合
#include <iostream>
#include <tuple>
using namespace std;
enum ColorInfo {
b,
g,
r,
};
int main(int argc, char* argv[]) {
using Color = std::tuple<char, int, double>;
Color color{'a', 6, 2.33f};
auto b = std::get<r>(color);
std::cout << b << "\n";
return 0;
}