2017-02-21 153 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)。