2015-11-02 105 views
-1

考慮這個簡單的代碼:爲什麼的std :: underlying_type <T>無符號當T是不是?

int main() { 
    enum Simple { one = 1, two = 2 }; 
    Simple m1 = static_cast<Simple>(-1); 
    if (m1 < 0) return -1; 
    return 1; 
} 

不出意外,這將返回-1。

令人驚訝的是,當我使用的std :: underlying_type <簡單>,基本類型是「無符號整型」。跆拳道?如果Simple的基礎類型是無符號的,它是如何得到小於零的?

進一步的證據:

int main(int argc, char *argv[]) { 
    enum Simple { one = 1, two = 2 }; 
    Simple m1 = static_cast<Simple>(-1); 

    std::underlying_type<Simple>::type underlying = m1; 

    long long llm1 = m1; 

    std::cout << "simple=" << m1 
      << " underlying=" << underlying 
      << " long long=" << llm1 
      << "\n"; 
} 

產地:

簡單= -1底層= 4294967295長長= 4294967295

+0

隱式轉換和積分的組合促銷,我會下注。 –

+1

如何編譯甚至不編譯,產生輸出? –

+0

而不'class'或顯式基礎類型的基礎類型枚舉是*實現定義*除了它不允許比'int'大的類型,除非統計員不能適合在'int'。你的第一個例子表明(在C++ 17之前!)你的編譯器使用一個簽名類型作爲基礎類型。如果'std :: underlying_type '實際上解析爲'unsigned int',那麼這兩種情況的組合將表示編譯器錯誤。但是你應該張貼一些證據表明'的std :: underlying_type '其實'根據你的要求 –

回答

2

讀數static_cast

8)整數的文檔,浮點型或枚舉類型可以轉換爲任何完整的枚舉類型。結果是未指定(直到C++ 17)undefined如果轉換爲枚舉的基礎類型的表達式的值超出範圍(如果基礎類型是固定的,則表達式的值爲範圍是該類型的範圍如果底層類型不固定,則範圍是所有可能的最小位域足以容納目標枚舉的所有枚舉數)

+0

「範圍」的定義對於非固定枚舉(這是哪一個)有些不清楚,但是對於任何帶符號的位域 –

+2

@ m.m,「-1」都在範圍內。 2位的無符號位字段足以存儲1和2. 2字節的有符號位字段不是。一般而言,對於所有正枚舉器的枚舉,無符號位字段將比所需的有符號位字段小1位;因此所需的最小位字段是唯一的,並且如果枚舉器都是正的,則總是無符號的。 – Yakk

+1

在其他消息中,我很高興看到'static_cast (-1)'可以導致硬盤在C++ 17中被格式化。在我們看到編譯器的第一種情況之前多久刪除一個函數的大塊,因爲它有一個代碼路徑通向那個? –

相關問題