多个枚举声明

More than one enum declaration

本文关键字:声明 枚举      更新时间:2023-10-16

这是N3797工作草案第3.3.4节的报价:

给定一个声明区域中的一组声明,每个它指定了相同的非限定名

——只能声明一个类名或枚举不是类型定义的名称和其他声明都应该引用相同的变量或枚举数,或者全部引用函数和函数模板;

我们可以在一个声明区域内多次声明enum类型名:

enum A; // declared first time, the other declaration with the same
        // unqualified name shall all refer to the same variable or enumeration.
enum A; // This and the other declarations shall all refer to the that enumeration
extern int A; // Fail, now enum A is hidden and we can access it
              // via elaborated-type-specifier only

我困惑。你能解释这种行为吗?我想找到当前工作草案的相应参考

完整报价n3797 3.1.4/4为:

给定一个声明区域中的一组声明,每个声明都指定了相同的非限定名,

—它们都指同一实体,或者都指函数和函数模板;或者

——只有一个声明必须声明非类型定义的类名或枚举名其他声明均应引用同一变量或枚举数,或均引用函数和函数模板;在这种情况下,类名或枚举名是隐藏的。

你写的代码是错误的。有关所需语法,请参阅S7.2,可以是以下任何一种:

enum A : int; // declaration (and it is an enumeration name)
enum A : int; // refers to the same entity
enum struct A; // declaration (and it is an enumeration name)
enum struct A; // refers to the same entity
enum A {}; // declaration (and it is an enumeration name)
enum A {}; // refers to the same entity

那么接下来的翻译单元中可能会出现以下情况。

extern int A; // declaration hides enumeration name
void f() {
  A j = A.a; // illegal. A is hidden
  int k = A; // legal
}

参见n3797 3.3.10/2:

类名(9.1)或枚举名(7.2)可以通过变量名、数据成员名、函数,或在同一作用域中声明的枚举数。如果类或枚举名与变量、数据成员、函数或枚举数在同一作用域中以相同的名称声明(以任何顺序),则类或枚举名将隐藏在变量、数据成员、函数或枚举数名可见的地方。

所以最后的A隐藏了前面的A。这是你想问的吗?


关于这个问题:程序是格式良好的吗?显然,这些只是片段,没有完整的程序,但如果这些是对A的唯一引用,那么它合法吗?我的回答是肯定的。S7.2/6说:

基础类型固定的枚举从其声明点(3.3.2)到其枚举基(如果有的话)之后都是不完整类型,此时它成为完整类型。基础类型不固定的枚举从其声明点到其枚举说明符结束}之后都是不完整类型,此时它成为完整类型。

因此,在每个给定的例子中,A是如图所示的完整类型。7.2/3说:

opaque-enum-declaration可以是当前范围内枚举的重新声明,也可以是新枚举的声明。[注:由opaque-enum声明声明的枚举具有固定的基础类型,并且是完整类型。]枚举数列表可以在以后用枚举说明符重新声明时提供。有作用域的枚举以后不得重新声明为无作用域或具有不同的基础类型。以后不得将未限定作用域的枚举重新声明为限定作用域的枚举,并且每次重新声明都应包括指定与原始声明相同的基础类型的enum-base。

因此,只要属性和基类相同,这些声明似乎就可以重复,但一旦提供了枚举数列表,可能就不能重复了。

对于前两个,程序似乎是格式良好的,但对于最后一个,可能就不是这样了。

我认为你做错了。Enumerator (enum)是一种类型,如果你写
enum A;
你给了这个类型一个名字,但是你仍然没有任何变量。有两种可能的声明方式。1. 你可以这样写:
enum A { a, b, c };
,现在你有3个变量{a, b, c},它们的类型是enum,类型名是a。第二种方法是:
enum NAME; NAME var1; NAME var2;
您还可以使用未命名的变量:
enum { a, b, c };
当您希望为常量命名,但不打算使用该类型来声明变量、函数参数等时,可以使用该类型。