C++0x 中 C++ 枚举的底层类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/853368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Underlying type of a C++ enum in C++0x
提问by criddell
I've been trying to read a bit of the C++ standard to figure out how enum's work. There's actually more there than I originally thought.
我一直在尝试阅读一些 C++ 标准来弄清楚 enum 是如何工作的。实际上那里的东西比我原先想象的要多。
For a scoped enumeration, it's clear that the underlying type is int
unless otherwise specified with an enum-base clause (it can be any integral type).
对于作用域枚举,int
除非用 enum-base 子句另行指定(它可以是任何整数类型),否则很明显底层类型是。
enum class color { red, green, blue}; // these are int
For unscoped enumerations, it seems like the underlying type can be any integral type that will work and that it won't be bigger than an int, unless it needs to be.
对于无作用域的枚举,底层类型似乎可以是任何可以工作的整数类型,并且它不会比 int 大,除非它需要。
enum color { red, green, blue}; // underlying type may vary
Since the underlying type of unscoped enumarations are not standardized, what's the best way of dealing with serializing instances of one? So far, I've been converting to int
when writing then serializing into an int
and setting my enum
variable in a switch when reading, but it seems a bit clunky. Is there a better way?
由于无作用域枚举的底层类型没有标准化,处理序列化实例的最佳方法是什么?到目前为止,我一直int
在写入时转换为,然后序列化为 anint
并enum
在读取时在 switch 中设置我的变量,但它似乎有点笨拙。有没有更好的办法?
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;
}
采纳答案by markh44
I haven't read any C++0x stuff so I couldn't comment on that.
我没有读过任何 C++0x 的东西,所以我无法对此发表评论。
As for serializing, you don't need the switch when reading the enum back in - just cast it to the enum type.
至于序列化,在读回枚举时不需要开关 - 只需将其转换为枚举类型。
However, I don't cast when writing to the stream. This is because I often like to write an operator<< for the enum so I can catch bad values being written, or I can then decide to write out a string instead.
但是,我在写入流时不会强制转换。这是因为我经常喜欢为枚举编写一个 operator<< 以便我可以捕获正在写入的错误值,或者我可以决定写出一个字符串。
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
回答by lothar
enum classis a C++0xfeature, it is not present in C++03.
枚举类是C++0x 的特性,它在 C++03 中不存在。
In standard C++, enumerations are not type-safe. They are effectively integers, even when the enumeration types are distinct. This allows the comparison between two enum values of different enumeration types. The only safety that C++03 provides is that an integer or a value of one enum type does not convert implicitly to another enum type. Additionally, the underlying integral type, the size of the integer, cannot be explicitly specified; it is implementation defined. Lastly, enumeration values are scoped to the enclosing scope. Thus, it is not possible for two separate enumerations to have matching member names. C++0x will allow a special classification of enumeration that has none of these issues. This is expressed using the enum class declaration
在标准 C++ 中,枚举不是类型安全的。它们实际上是整数,即使枚举类型不同。这允许在不同枚举类型的两个枚举值之间进行比较。C++03 提供的唯一安全是整数或一种枚举类型的值不会隐式转换为另一种枚举类型。此外,无法明确指定底层整数类型,即整数的大小;它是实现定义的。最后,枚举值的范围限定为封闭范围。因此,两个单独的枚举不可能具有匹配的成员名称。C++0x 将允许枚举的特殊分类,没有这些问题。这是使用枚举类声明表示的
Examples (from the wikipedia article):
示例(来自维基百科文章):
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.
As for the serialization part (which I think was not part of the original question), I prefer to create a helper class that translates enum items into their string equivalent (and back), as the names are usually more stable than the integer values they represent, as enum items can be (and sometimes are) reordered without changing the code behavior.
至于序列化部分(我认为这不是原始问题的一部分),我更喜欢创建一个帮助类,将枚举项转换为等效的字符串(并返回),因为名称通常比它们的整数值更稳定表示,因为枚举项可以(有时是)重新排序而不改变代码行为。
回答by Johannes Schaub - litb
I decided to create a new answer because my old was so messy. Anyway just want to say something about C++11, where you can get the underlying type of an enumeration using this one:
我决定创建一个新答案,因为我的旧答案太乱了。无论如何只想说一些关于 C++11 的事情,在那里你可以使用这个来获取枚举的底层类型:
std::underlying_type_t<E>
And for the sake of interest, the overload resolution idea. But please use names to store the enumeration, as proposed by @lothar.
为了兴趣,重载决议的想法。但是请按照@lothar 的建议使用名称来存储枚举。
The overload resolution stems from the fact that there exist one promotion from an enumeration to the first of int, unsigned int, long, unsigned long that can represent all values of its underlying type. A conversion to any other integer type is lower ranked and overload resolution won't prefer it.
重载决议源于这样一个事实,即存在从枚举到 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>();
}
And it prints this one here:
它在这里打印了这个:
int
unsigned int
int
unsigned int
It's not of particular interest to this serialization problem (since the size of the data serialized is not of constant width, and this can cause problems when the enumeration and its underlying type is changed), but it is generally interesting to figure out a type storing the whole of an enumeration. Cheers!
这个序列化问题不是特别有趣(因为序列化的数据的大小不是恒定宽度,这会在枚举及其底层类型改变时导致问题),但是找出一个类型存储通常很有趣整个枚举。干杯!
回答by jaroslav ?míd
#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;
回答by Dario
As to enum class color
: Is this C++/CLI (C++ .NET) or future C++0x code?
至于enum class color
:这是 C++/CLI (C++ .NET) 还是未来的 C++0x 代码?
For serialization, you could get the enum's size with sizeof(color)
to know how many bytes to copy.
对于序列化,您可以获得枚举的大小sizeof(color)
以了解要复制的字节数。