在强类型枚举中无条件要求显式范围解析的背后原理是什么?
N2347解释了与老式枚举的区别,它们没有隐式转换,没有指定存储类型的能力,并且没有在周围范围内注入(inject)名称(例如C++ 03,它具有C的传统)。
换句话说,像在C++ 03中那样编写enum E1 { a, b, c};
与编写类似
const int a = 1; const int b = 2; const int c = 3;
而C++ 11中的
enum E1 class { a, b, c};
与类似namespace E1 { const int a = 1; const int b = 2; const int c = 3; }
(不引入 namespace ,并且在两种情况下都定义枚举类型)。
现在,我通常不了解哪里有歧义,假设一个人具有例如以下代码(不会编译):
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需要显式范围解析,即使没有其他可能的方式来解释代码。
在我看来,可以预期
void foo(E1 e);
的含义更像void foo(using enum E1; E1 e);
(我的语法当然完全错误,但是您明白了),这是合理的。以同样在N2347中使用的
Color
和Alert
的“经典”示例为例,它具有红色警报和红色,也可能是不同的数字常数。没有强类型保证,可以想象当一个人确实想要例如一个在显示器上设置红色。或者,通过整数转换和宽松的函数声明,可以想象有人最终会使用yellow|red
之类的东西来获取橙色。这一切都是不可能的,那么我们到底要捍卫什么呢?
最佳答案
表达式的类型必须是已知的。并且由于将a
用作独立表达式是不明确的,因此在任何地方使用a
都是不明确的。
您不希望表达式根据其所使用的上下文来更改其含义。1 + 1
始终意味着同一件事。如果您使用相同的1 + t
,t
始终意味着同一件事。同样,不管在哪里使用a
,都应始终表示相同的意思。
C++中唯一允许根据使用上下文推导源类型的方法是统一初始化。并且该标准明确指出“括号初始列表”不是表达式。 a
是一个表达式,因此它遵循表达式规则。