【问题标题】:More than one enum declaration多个枚举声明
【发布时间】:2014-05-17 08:01:57
【问题描述】:

有来自秒的报价。 N3797工作草案的3.3.1/4:

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

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

我们可以在单个声明区域中多次声明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

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

【问题讨论】:

  • No we cannot 多次声明 enum 类型名称。事实上,we cannot 甚至声明了一次,就像你展示的那样。
  • @IgorTandetnik 但是定义为enum-key attribute-specifier-seq_opt identifier enum-base_optopaque-enum-declaration呢。
  • 不是你的。 7.2/2 声明无范围枚举的 opaque-enum-declaration 不得省略 enum-base
  • @IgorTandetnik 您确定您查看的是我在帖子中指定的相同工作草案(N3797 C++14 工作草案)吗?

标签: c++ enums language-lawyer


【解决方案1】:

n3797 3.3.1/4 的完整报价是:

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

——它们都应该引用同一个实体,或者都引用函数和函数模板;或

——只有一个声明应该声明一个不是 typedef 名称的类名或枚举名 其他声明均指同一个变量或枚举数,或均指函数和函数模板;在这种情况下,类名或枚举名是隐藏的。

你写的代码是错误的。有关所需语法,请参阅 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-declaration 声明的枚举具有固定的底层类型,并且是完整的类型。枚举器列表可以在稍后的重新声明中使用枚举说明符提供。 —结束注释] 以后不应将范围枚举重新声明为无范围或具有不同的基础类型。以后不应将无作用域枚举重新声明为作用域,并且每个重新声明都应包含一个枚举基,指定与原始声明中相同的基础类型。

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

对于前两个来说,该程序似乎是结构良好的,但可能不是最后一个。

【讨论】:

  • 假设那些enum-声明实际上是合法的,例如enum class A; enum class A;enum A : int; enum A : int;。那么,尽管有不只是一个声明来声明枚举名称,那么程序是否格式正确?
  • 程序是合法的(不包括非法赋值)。设置基本类型或范围不会改变这一点(只要它们引用相同的实体)。如果您有更复杂的想法,您可能需要提出一个新问题。
  • enum A; 肯定是不合法的,因为Igor Tandetnik 也在 cmets 中向 OP 指出。对于无范围枚举的前向声明,您不能省略 enum-base。我的实际问题是关于枚举的两个声明。 3.3.1/4 说“只有一个声明应该声明一个 [...] 枚举名称”,这里我们有两个声明一个枚举名称。因此,据我所知,隐藏的要求并不成立。
  • @dyp:我不同意。 enum A; 在我阅读 n3797 s7.2 opaque-enum-declaration 时是合法的。请以其他方式显示。
  • @dyp:见编辑。现在好多了?对于您最初的问题,通过我的阅读,程序格式正确(7.2/3:is a complete type)无论如何都没有假设这些代码片段构成了整个翻译单元,更不用说整个程序了。
【解决方案2】:

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

【讨论】:

  • 看来,你不明白我的意思。我想了解正式的 c++ 语言规则。我对这个问题的可用性不感兴趣。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多