Visual studio 2010没有限定作用域的opaque-enum声明,省略了base

Visual studio 2010 unscoped opaque-enum-declarartion with omitted base

本文关键字:声明 opaque-enum base 作用域 2010 studio Visual      更新时间:2023-10-16

下面的代码在编译/链接时没有错误或警告

enum E;
enum E;
int _tmain(int argc, _TCHAR* argv[]){ }

是VS2010的bug吗?

您的代码可以使用vc++ 2010及更高版本的MS语言扩展进行编译您可以使用编译器标志/Za禁用。

乍一看,

enum E;
enum E; 

看起来就像enum E的两个前向声明。这样看来,重复就不存在了相关的。N的前向声明并不比一个更合法,所以启用MS扩展(/Ze)似乎包括启用前向enum声明,在c++ 03 或c++ 11 中是非法的。

但是这种外观是误导的,如下面的程序所示:

#include <iostream>
enum E;
//enum E;
enum E e;
int main()
{
    std::cout << (e == 0) << std::endl;
    return e;
}

这也可以在vc++ 2010或更高版本中编译干净,证明编译器不会将enum E;解析为E正向声明,而是将其解析为定义

这里的语言扩展是enum E;,乍一看,等同于enum E {}

如果我们取消程序中的//enum E;注释,它仍然可以编译干净,这在第二遍中显示出来随后,enum E;不是再次解析为定义,就像E的重新声明一样。

vc++ 2013支持c++ 11中作用域和基于的枚举的概念。禁用扩展后,它将编译并拒绝如下代码所示的声明:
enum UnscopedBasedEnum : int; // :)
enum UnscopedBasedEnum : int; // :)
UnscopedBasedEnum ube; // :)
enum struct ScopedBaselessEnum; // :)
enum struct ScopedBaselessEnum; // :)
ScopedBaselessEnum sbe;
//enum UnscopedBaseLessEnum; // :(

所有这些都是c++ 11兼容的。

然而,ubesbe的声明证明了没有这里的声明是前向声明,如果前向声明具有习惯意义不完整类型的声明。如果UnscopedBasedEnum | ScopedBaselessEnum如果在这些声明中是一个不完整的类型,那么ube | sbe的声明将会是将声明不完整类型的对象,并且不会编译。在c++ 11中,声明UnscopedBasedEnumScopedBaselessEnum的值是不透明的enum声明,这意味着没有存在或暗示枚举数列表。但他们仍然宣布完成

opaque-enum-declaration要么是当前范围内枚举的重新声明,要么是声明一个新枚举的。[注:由不透明枚举声明声明的枚举具有固定的底层。类型和是一个完整类型。枚举数列表可以在以后使用枚举说明符重新声明时提供。-end note]

您在这里所做的是enum向前声明。一些编译器(比如VS)提供了语言扩展,在c++ 11之前的标准中支持这种行为。您可以通过禁用项目设置中的语言扩展来验证这一点,这将导致编译器错误。c++没有这样的扩展,但在添加大小说明符或使用enum class时,它应该使用-std=c++11编译代码。

在启用了编译器扩展的情况下在Visual Studio中有效

enum E;
enum E;

在所有支持c++ 11的编译器中有效

enum class E;
enum class E;
// or
enum E : short;
enum E : short;