枚举声明中枚举器的类型
Type of an enumerator in the declaration of its enum
在 C++ 中,特别是在 C++14 n4296 中,有两个段落谈论枚举器的类型,这对我来说似乎是矛盾的。参见 7.2/5(即 n4659
中的 10.2/5):
Each enumeration defines a type that is different from all other types. Each enumeration also has an underlying type. The underlying type can be explicitly specified using an enum-base. For a scoped enumeration type, the underlying type is int if it is not explicitly specified. In both of these cases, the underlying type is said to be fixed. Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration. If the underlying type is fixed, the type of each enumerator prior to the closing brace is the underlying type and the constant-expression in the enumerator-definition shall be a converted constant expression of the underlying type [...]
而 5.1.1/11(即 n4659
中的 8.1.4.2/4)写道:
A nested-name-specifier that denotes an enumeration (7.2), followed by the name of an enumerator of that enumeration, is a qualified-id that refers to the enumerator. The result is the enumerator. The type of the result is the type of the enumeration. The result is a 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 中的标准自相矛盾
The result is the enumerator. (1)
和
The type of the result is the type of the enumeration. (2)
如果 (1) 为真,则结果类型应为枚举器的类型,根据 7.2/5,它要么是枚举的基础类型,要么是枚举定义的类型,具体取决于它是否在右大括号之前或之后。
意味着您的代码示例应该可以正常编译,因为 E::B
是 B
并且 B
的类型是 short
.
现在,如果您考虑 (2),它在右大括号后不会发生任何变化。但是如果(2)在右大括号前为真,则表示E::B
的类型是E
同时B
的类型是short
,所以你最终得到 E::B != B
这与 (1).
相矛盾
在 C++ 中,特别是在 C++14 n4296 中,有两个段落谈论枚举器的类型,这对我来说似乎是矛盾的。参见 7.2/5(即 n4659
中的 10.2/5):
Each enumeration defines a type that is different from all other types. Each enumeration also has an underlying type. The underlying type can be explicitly specified using an enum-base. For a scoped enumeration type, the underlying type is int if it is not explicitly specified. In both of these cases, the underlying type is said to be fixed. Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration. If the underlying type is fixed, the type of each enumerator prior to the closing brace is the underlying type and the constant-expression in the enumerator-definition shall be a converted constant expression of the underlying type [...]
而 5.1.1/11(即 n4659
中的 8.1.4.2/4)写道:
A nested-name-specifier that denotes an enumeration (7.2), followed by the name of an enumerator of that enumeration, is a qualified-id that refers to the enumerator. The result is the enumerator. The type of the result is the type of the enumeration. The result is a 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 中的标准自相矛盾
The result is the enumerator. (1)
和
The type of the result is the type of the enumeration. (2)
如果 (1) 为真,则结果类型应为枚举器的类型,根据 7.2/5,它要么是枚举的基础类型,要么是枚举定义的类型,具体取决于它是否在右大括号之前或之后。
意味着您的代码示例应该可以正常编译,因为 E::B
是 B
并且 B
的类型是 short
.
现在,如果您考虑 (2),它在右大括号后不会发生任何变化。但是如果(2)在右大括号前为真,则表示E::B
的类型是E
同时B
的类型是short
,所以你最终得到 E::B != B
这与 (1).