在强类型枚举中无条件要求显式范围解析的背后原理是什么?

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中使用的ColorAlert的“经典”示例为例,它具有红色警报和红色,也可能是不同的数字常数。没有强类型保证,可以想象当一个人确实想要例如一个在显示器上设置红色。或者,通过整数转换和宽松的函数声明,可以想象有人最终会使用yellow|red之类的东西来获取橙色。

这一切都是不可能的,那么我们到底要捍卫什么呢?

最佳答案



表达式的类型必须是已知的。并且由于将a用作独立表达式是不明确的,因此在任何地方使用a都是不明确的。

您不希望表达式根据其所使用的上下文来更改其含义。1 + 1始终意味着同一件事。如果您使用相同的1 + tt始终意味着同一件事。同样,不管在哪里使用a,都应始终表示相同的意思。

C++中唯一允许根据使用上下文推导源类型的方法是统一初始化。并且该标准明确指出“括号初始列表”不是表达式。 a是一个表达式,因此它遵循表达式规则。

10-07 12:56