在C++中,枚举[tag] [:类型] {枚举列表} [声明符]是否合法?

7
我正在使用C++中的自定义枚举类型,但它没有很多值。我想尝试减少它们占用的空间大小,并听说枚举类型 默认情况下总是整数。然后我发现了C++枚举的MSDN条目,并发现以下语法非常有趣:
enum [: type] {enum-list};

当我按照以下步骤操作时,我的代码终于编译成功了(使用我想要的VS2008版本):

enum plane : unsigned char { xy, xz, yz };

现在,你可以从我的枚举常量中看到,我在空间方面并不需要太多 - 无符号 char 类型对我的用途来说完美。

然而,我必须说,我从未在互联网上看到过这种形式被使用 - 大多数人甚至似乎都不知道。我正在尝试使这个代码跨平台(可能用于嵌入式系统),所以让我想知道......这是正确的 C++ 语法,还是只受 MSVC 编译器支持?

编辑: 看起来,这个特性现在是 C++11 及以上版本的一部分,被称为 作用域枚举


4
你听说过“过早优化”吗?如果你有大量的枚举数组,这可能会很重要。否则,它很可能属于过早优化的范畴。检查代码大小,甚至可能会增加操纵枚举值所需的代码量。 - Jonathan Leffler
@Jonathan Leffler,我正在考虑使用#define宏或者只是封装在命名空间中的const变量来实现这个... 我只是想确定我的所有选项。我认为使用这种方法的语法既方便又直观。 - Breakthrough
澄清:根据C++03标准,枚举不是整数类型;但是,它们可以提升为int、unsigned int、long或unsigned long。此外,由于枚举不是lvalue,因此它们既没有存储期也没有链接。请参见:http://www.eetimes.com/discussion/programming-pointers/4023879/Enumeration-Constants-vs-Constant-Objects - Gnawme
就我个人而言,我认为对问题进行的这次小更新并不值得在将近七年后将其推到首页。严格来说,它可能甚至不应该出现在问题中——它是一个答案,应该放在那里(事实上,它已经在那里了!) - anon
3个回答

7
这是非标准的,但预计会成为C++0x标准的一部分。对于我来说,在将警告级别设置为最高的Visual Studio 2005中编译时,我会收到以下警告:warning C4480: nonstandard extension used: specifying underlying type for enum 'Test'
C++0x的维基百科页面上可以看到:
在标准C++中,枚举类型不具备类型安全性。即使枚举类型是不同的,它们实际上也是整数。这允许比较两个不同枚举类型的枚举值。C++03提供的唯一安全性是,一个整数或一个枚举类型的值不能隐式转换为另一个枚举类型。此外,底层整数类型是由实现定义的。依赖于枚举大小的代码因此是不可移植的。最后,枚举值被限定在封闭范围内。因此,两个单独的枚举无法具有匹配的成员名称。
此外,C++0x还允许标准枚举提供显式作用域以及定义底层类型。
enum Enum3 : unsigned long {Val1 = 1, Val2};

我认为你已经明白了。我一直在尝试在C++标准中找到这个,但没有找到任何信息,所以我会假设它不被支持。感谢您的回答,+1! - Breakthrough
2
@突破:MSDN页面应该告诉你这个,但它没有! - user195488
太棒了,看起来C++11及以上版本的作用域枚举已经有很好的文档支持了,对于这个特性感到非常高兴。 - Breakthrough

2
正如0A0D所说,你使用的符号在C++03中是非标准的,但已被C++11采纳,并被称为“作用域枚举”。
如果这对你来说不够快,那么你可以考虑在嵌入它们的大小关键结构中显式指定用于枚举字段的位域宽度。这种方法很丑陋 - 我提到它只是为了完整性;如果这是一个好的解决方案,上面的符号就不会被C++11采用了。一个问题是你依赖可选的编译器警告来检测过小的位域以容纳可能的值,并且在枚举值改变时可能需要手动进行审核。
例如:
enum E
{
    A, B, C
};

struct X
{
    E e1 : 2;
    E e2 : 2;
    E e3 : 2;
    E e4 : 2;
};

注意:枚举可能占用比请求的位数更多的位 - 在没有显式编译器选项的情况下,GCC 4.5.2上的sizeof(X)仍然为4。

0

这是完全合法的。然而,为了节省空间,在对象中嵌入类型如果没有特别确保对齐,将不会有效果。如果您保留默认对齐方式,填充字节将被添加(取决于架构),通常会添加到四字边界。


1
由于这被标记为Visual Studio,因此它是合法的,也就是说受到支持(尽管作为Microsoft特定的非标准扩展)。它在Visual Studio 2005和Visual Studio 2008的文档中明确引用:http://msdn.microsoft.com/en-us/library/2dzy4k6e%28v=vs.90%29.aspx 此外,正如上面所述,这将在C++0x标准中被特别允许。 - Chad
1
我们如何定义合法?在集成开发环境中打开充足的警告后,它会警告你它是非标准的。 - user195488
由于它目前是一个微软特定的扩展,因此被标记为“Visual-Studio”,并且如果您使用底层类型说明符,则分配给该枚举的存储将与您基于类型所期望的匹配,我在这种情况下定义它是合法的。随着C++0x的发展(Microsoft Visual Studio 2010已经有很好的支持),除了所有警告之外,它将是合法的。 - Chad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接