2017-02-21 156 views
6

在C++中,特别是在C++ 14 n4296中,有两个章节讨论枚举类型,这似乎与我相矛盾。见7.2/5(其是10.2/5在n4659):枚举声明中枚举数的类型

每个枚举定义了类型,它是从所有其他类型不同。每个枚举也有一个基础类型。基础类型可以使用enum-base明确指定。对于范围枚举类型,如果未明确指定,则基础类型为int。在这两种情况下,底层类型都被认为是固定的。在enum-specifier的大括号之后,每个枚举器都有其枚举类型。 如果基础类型是固定的,则在大括号之前的每个枚举器的类型是基础类型,并且枚举器定义中的常量表达式应该是基础类型的转换常数表达式[012]

而且5.1.1/11(其是在n4659 8.1.4.2/4)写道:

嵌套名说明符,它表示一个枚举(7.2),接着是枚举的名称该枚举是一个指向枚举数的合格标识。结果是枚举器。 结果的类型是枚举类型。结果是一个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。

+1

请注意:C++ 17(n4618)中的5.1.1/11是5.1.4.2/4。 – kennytm

回答

3

我认为标准自相矛盾这里您在5.1.1/11

结果已经是枚举。 (1)

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

如果(1)为真,则结果类型应是枚举,其中,根据7.2/5,或者是基础类型枚举的或由所定义的类型的类型枚举取决于它是在大括号之前还是之后。

这意味着您的代码示例应该编译得很好,因为E::BBB的类型是short

现在,如果考虑到(2),它在大括号之后不会改变任何内容。但是如果(2)在大括号之前为真,这意味着E::B的类型为E,同时B的类型为short,所以最终与E::B != B相冲突(1)。