我一直试图阅读一些C++标准来弄清楚枚举是如何工作的.实际上比我原先想象的更多.
对于作用域枚举,int
除非使用enum-base子句(它可以是任何整数类型)另外指定,否则基本类型是明确的.
enum class color { red, green, blue}; // these are int
Run Code Online (Sandbox Code Playgroud)
对于无范围的枚举,似乎底层类型可以是任何可以工作的整数类型,并且它不会大于int,除非它需要.
enum color { red, green, blue}; // underlying type may vary
Run Code Online (Sandbox Code Playgroud)
由于基础类型的无范围激励不是标准化的,处理序列化实例的最佳方法是什么?到目前为止,我一直在转换到int
写入时串行化int
并enum
在读取时将变量设置在开关中,但它似乎有点笨拙.有没有更好的办法?
enum color { red, green, blue };
color c = red;
// to serialize
archive << (int)c;
// to deserialize
int i;
archive >> i;
switch(i) {
case 0: c = red; break;
case 1: c = green; break;
case 2: c = blue; break;
}
Run Code Online (Sandbox Code Playgroud)
lot*_*har 16
enum类是C++ 0x特性,它在C++ 03中不存在.
在标准C++中,枚举不是类型安全的.即使枚举类型不同,它们也是有效的整数.这允许比较不同枚举类型的两个枚举值.C++ 03提供的唯一安全性是整数或一个枚举类型的值不会隐式转换为另一个枚举类型.另外,不能明确指定底层整数类型,即整数的大小; 它是实现定义的.最后,枚举值的范围限定为封闭范围.因此,两个单独的枚举不可能具有匹配的成员名称.C++ 0x将允许枚举的特殊分类,没有这些问题.这是使用枚举类声明表示的
示例(来自维基百科文章):
enum Enum1; //Illegal in C++ and C++0x; no size is explicitly specified.
enum Enum2 : unsigned int; //Legal in C++0x.
enum class Enum3; //Legal in C++0x, because enum class declarations have a default type of "int".
enum class Enum4: unsigned int; //Legal C++0x.
enum Enum2 : unsigned short; //Illegal in C++0x, because Enum2 was previously declared with a different type.
Run Code Online (Sandbox Code Playgroud)
至于序列化部分(我认为它不是原始问题的一部分),我更喜欢创建一个帮助类,它将枚举项转换为它们的字符串等效(并返回),因为名称通常比整数值更稳定表示,因为枚举项可以(有时是)重新排序而不改变代码行为.
Joh*_*itb 14
我决定创建一个新答案,因为我的老人太乱了.无论如何只想说一些关于C++ 11的东西,你可以使用这个来获取枚举的基础类型:
std::underlying_type_t<E>
Run Code Online (Sandbox Code Playgroud)
并且为了兴趣,重载决策的想法.但请使用名称来存储枚举,如@lothar所提议的那样.
重载决策源于以下事实:从枚举到第一个int,unsigned int,long,unsigned long存在一个可以表示其基础类型的所有值的提升.转换为任何其他整数类型的排名较低,重载决策不会更喜欢它.
char (& f(int) )[1];
char (& f(unsigned int) )[2];
char (& f(long) )[3];
char (& f(unsigned long) )[4];
char const* names[] = {
"int", "unsigned int",
"long", "unsigned long"
};
enum a { A = INT_MIN };
enum b { B = UINT_MAX };
enum c { C = LONG_MIN };
enum d { D = ULONG_MAX };
template<typename T> void print_underlying() {
std::cout << names[sizeof(f(T()))-1] << std::endl;
}
int main() {
print_underlying<a>();
print_underlying<b>();
print_underlying<c>();
print_underlying<d>();
}
Run Code Online (Sandbox Code Playgroud)
它在这里打印这个:
int
unsigned int
int
unsigned int
Run Code Online (Sandbox Code Playgroud)
这个序列化问题并不特别引人关注(因为序列化数据的大小不是恒定的宽度,这可能会在枚举及其基础类型发生变化时引起问题),但通常很有意思的是找出一个类型存储整个枚举.干杯!
我还没有读过任何C++ 0x的东西,所以我无法对此发表评论.
至于序列化,在重新读取枚举时不需要切换 - 只需将其转换为枚举类型.
但是,在写入流时我没有强制转换.这是因为我经常喜欢为枚举编写一个运算符<<,这样我就可以捕获写入的错误值,或者我可以决定写出一个字符串.
enum color { red, green, blue };
color c = red;
// to serialize
archive << c; // Removed cast
// to deserialize
int i;
archive >> i;
c = (color)i; // Removed switch
Run Code Online (Sandbox Code Playgroud)
小智 5
#include <type_traits>
enum a { bla1, bla2 };
typedef typename std::underlying_type<a>::type underlying_type;
if (std::is_same<underlying_type, int>::value)
std::cout << "It's an int!" << endl;
else if (std::is_same<underlying_type, unsigned int>::value)
std::cout << "It's an uint!" << endl;
Run Code Online (Sandbox Code Playgroud)