2009-07-28 83 views
2

我們有一個用於數字數據類型的模板轉換函數。它裏面包含一個構造,使得它不能像指針一樣編譯。乘法如何爲C++枚舉工作?

template<class To, class From> 
To ConvertTo(From what) 
{ 
    assert(2 * what == what * 2); // this will not compile for pointers 
    //skipped 
} 

此功能編譯和工作好吧當枚舉作爲第二模板參數傳遞:

enum TSomeEnum { 
    SE_First, 
    SE_Second  
}; 

TSomeEnum enumValue = SE_First; 
int result = ConvertTo<int>(enumValue); 

以上代碼編譯和運行按預期在VC++ 7。

操作*如何爲枚舉工作?這是一種未定義的行爲嗎?

回答

5

枚舉降級爲整數(舊C特徵),以便爲什麼這是行得通的。我不認爲這是不確定的行爲,儘管它可能是你不想要的行爲。

+6

Enum的降級爲某種能夠存儲枚舉值的底層整型。降級到'int'對於C++來說是不正確的。 – 2009-07-28 12:22:32

0

枚舉存儲爲整數,甚至可以轉換爲整數。

編譯器可能存儲在上面的枚舉作爲

enum TSomeEnum { 
    SE_First = 0, 
    SE_SEcond = 1 
}; 

我不知道,如果這種編號系統中的C/C++標準或編譯器是如何做到這一點,但我一直按順序看過他們。

無論如何,要回答你的問題,因爲它們存儲爲下方的整數,所以它應該可以相乘。儘管一些編譯器可能會給你一個關於類型轉換的警告。

+0

看到我的評論重新「整數」的其他兩個職位。重新設定值,標準保證第一個枚舉器(沒有明確的初始化)將具有零值。每個隨後的枚舉器都有一個前一個枚舉器的值+1,除非你指定一個明確的值。 – 2009-07-28 12:27:07

2

枚舉被提升爲整數進行算術運算。

枚舉值總是從零開始編號(這是標準的一部分),但是您可以指定任何您喜歡的值。自動編號然後從您明確編號的最後一個項目開始逐步進行。 編譯器使用包含枚舉的所有值來存儲它的最小整數類型。

如:

enum foo 
{ 
    VALUE0, /* = 0 */ 
    VALUE1, /* = 1 */ 
    VALUE3 = 1234, 
    VALUE4 /* = 1235 */ 
}; 
+0

枚舉有一個基礎表示。在這種情況下,這可能是'signed char',但它們會被提升爲int,但是,底層類型也可能是unsigned int,因此不會進行升級。 – 2009-07-28 12:24:29

2

我認爲peterchen具有理想的答案,但如果升壓是你太多,你的當前版本更改爲:

template<class To, class From> 
To ConvertTo(From what, From checkConvertableToInt = 2) 
{ 
} 

C++沒有按」允許從整數到枚舉的隱式轉換。同樣,只能將空指針常量(0)隱式轉換爲指針類型。

其他一些答案指的是作爲int實現的枚舉或被提升爲int的枚舉。這不是真的。在C++中,枚舉被定義爲具有能夠在枚舉中存儲所有值的基礎類型。因此,以下列舉將有一個基本類型「無符號整型」或更大的符號/無符號整數類型:

enum E { 
    E0 
    , E1=MAX_INT+1u 
}; 

枚舉然後遵循規則,其基本類型,當你在操作中使用它。

+1

+1使用賦值來測試枚舉,但要注意帶有副作用的斷言。 – iain 2009-07-28 12:59:57

1

Richard Corden的回答給出了一個很好的機制來強制枚舉在斷言中失敗,但副作用可能會導致問題,因爲您無法確定斷言中的代碼將始終運行。

此測試應該可能通過放置在通用函數中以避免副作用。

template<class To, class From> 
To ConvertTo(From what) 
{ 
    assert(testIntegralType(what)); 
} 

template<class T> 
void testIntegralType(T val) 
{ 
    T v1 = val; 
    assert(2*v1 == 2*val); 
}