枚举声明中的枚举器的类型



在C++中,特别是在C++14 n4296中,有两个参数在谈论枚举器的类型,这对我来说似乎是矛盾的。参见 7.2/5(即 10.2/5 英寸n4659):

每个枚举定义一个不同于所有其他类型的类型。每个枚举还有一个基础类型。可以使用枚举基显式指定基础类型。对于作用域枚举类型,如果未显式指定基础类型,则基础类型为 int。在这两种情况下,基础类型都称为固定类型。在枚举说明符的右大括号之后,每个枚举器都有其枚举的类型。如果基础类型是固定的,则右大括号之前每个枚举器的类型是基础类型,枚举器定义中的常量表达式应是基础类型的转换常量表达式 [...]

5.1.1/11(n4659中的 8.1.4.2/4)写道:

表示枚举 (7.2) 的嵌套名称说明符,后跟该枚举的枚举器的名称,是引用枚举器的限定 ID。结果是枚举器。结果的类型是枚举的类型。结果是一个 prvalue。

那么,当我们在声明的右大括号之前通过嵌套名称说明符引用枚举器时会发生什么?以以下代码片段为例:

template < typename T1, typename T2 >
struct fail_if_not_same {
static_assert(std::is_same<T1, T2>::value, "Fail!");
static constexpr int value = 0;
};
enum class E : short {
A,
B = A + 1,
C = fail_if_not_same<decltype(B), short>::value,
D = fail_if_not_same<decltype(E::B), short>::value
};

上面E::B的表达式的类型是什么?这是标准的矛盾吗?gcc 和 clang 都遵循 7.2/5。

我认为该标准在这里自相矛盾,就像您在 5.1.1/11 中所做的那样

结果是枚举器。(1)

结果的类型是枚举的类型。(二)

如果 (1) 为 true,则结果类型应为枚举器的类型,根据 7.2/5,枚举要么是枚举的基础类型,要么是枚举定义的类型,具体取决于它是在右大括号之前还是之后。

这意味着您的代码示例应该可以很好地编译,因为E::BB并且B的类型是short

现在,如果您考虑 (2),它在右大括号后不会改变任何内容。但是,如果在右大括号之前 (2) 为真,则意味着E::B的类型E,同时B的类型是short的,因此您最终会得到与 (1) 相矛盾的E::B != B

最新更新