2

在强类型枚举中无条件地要求明确范围解析的基本原理是什么?

N2347 解释了与老式枚举的区别,后者没有隐式转换、指定存储类型的能力以及在周围范围内没有注入名称(如在 C++03 中,它具有 C 的遗产)。

换句话说,enum E1 { a, b, c};在 C++03 中编写类似于编写

const int a = 1; const int b = 2; const int c = 3;

enum E1 class { a, b, c};在 C++11 中更类似于类似

namespace E1 { const int a = 1; const int b = 2; const int c = 3; }

(没有引入命名空间,并且在任何一种情况下都定义了枚举类型)。

现在,我通常不明白哪里有歧义,假设一个示例代码如下(不会编译):

enum class E1 { a, b, c };
enum class E2 { a, b, c }; // allowed now

void foo(E1 e) { ... }
void bar(E2 e) { ... }
void baz(int e) { ... }

foo(a);   // not ambigious: E1 expected, nothing but E1::a possible
bar(a);   // not ambigious: E2 expected, nothing but E2::a possible
baz(a);   // not ambigious: illegal - no name `a` in global scope

E1 x = a; // not ambigious: E1 expected, nothing but E1::a possible

在某些情况下,我欢迎(可选)显式范围解析以指出发生了什么,但我不明白为什么 C++11 需要显式范围解析,即使没有可能的方式以另一种方式解释代码。

在我看来,期望 examplevoid foo(E1 e);的含义更像是void foo(using enum E1; E1 e);(我的语法当然完全错误,但你明白了)是合理的。

以N2347中的Colorand的“经典”示例为例,其中一个具有red alertred,它们也可能是不同的数字常量。如果没有强类型保证,可以想象当一个人真的想在显示器上设置红色时,最终会使用警报数字常量。或者,通过整数转换和宽松的函数声明,可以想象有人最终会使用类似获取橙色的东西。Alertyellow|red

这些都不可能,那么我们到底要防御什么?

4

1 回答 1

5

富(一);// 没有歧义:预期 E1,只有 E1::a 可能

必须知道表达式的类型。并且由于a作为独立表达的使用是模棱两可的,所以a任何地方的使用都是模棱两可的。

您不希望表达式根据它们所使用的上下文来改变它们的含义。1 + 1总是意味着同样的事情。1 + t如果你使用相同的,总是意味着同样的事情t。同样,a无论在哪里使用,都应该始终表示相同的意思。

C++ 中唯一允许根据使用它的上下文推断源类型的是统一初始化。并且该标准明确指出“braced-init-list”不是表达式。a是一个表达式,所以它遵循表达式规则。

于 2012-11-08T17:02:49.197 回答