2013-02-20 84 views
33

是否有可能確定一個C enum class的++基數:是否可以確定一個C++枚舉類的元素的數量?

enum class Example { A, B, C, D, E }; 

我試圖使用sizeof,但是,它返回一個枚舉元素的大小。

sizeof(Example); // Returns 4 (on my architecture) 

是否有一個標準的方法來獲得基數(在我的例子中是5)?

+0

我想可能有一個特定的c + + 11機制 – bquenin 2013-02-20 20:32:32

+4

順便說一句,這不是重複的。 'enum'和'enum class''是非常不同的概念。 – Shoe 2013-12-02 02:13:03

+0

@Shoe ......他們真的嗎? – 2016-09-06 19:55:44

回答

43

不是直接的,但你可以使用下面的技巧:

enum class Example { A, B, C, D, E, Count }; 

然後基數可作爲(int)Example::Count

當然,如果你讓枚舉的值自動分配,從0開始,這隻會很好地工作。如果不是這種情況,你可以手動分配正確的基數到計數,這實際上沒有什麼不同反正維護單獨的常數:

enum class Example { A = 1, B = 2, C = 4, D = 8, E = 16, Count = 5 }; 

的一個缺點是,編譯器將允許您使用Example::Count作爲一個枚舉值的參數 - 如果你使用這個,所以要小心! (儘管我個人發現這在實踐中並不是問題)。

+5

雖然如果任何值被設置爲默認值以外的值,這會中斷。所以,小心使用。 – juanchopanza 2013-02-20 20:31:32

+0

好的謝謝你的提示 – bquenin 2013-02-20 20:31:39

+1

枚舉值在枚舉類中是類型安全的,所以'Count'的類型將是Example,而不是int,對吧?您必須先將「計數」轉換爲int,才能將其用於大小。 – 2015-03-26 13:29:23

1

不,你必須寫在代碼中。

3

您可以嘗試的一個技巧是在列表末尾添加一個枚舉值,並將其用作大小。在您的例子

enum class Example { A, B, C, D, E, ExampleCount }; 
5
enum class TEST 
{ 
    BEGIN = __LINE__ 
    , ONE 
    , TWO 
    , NUMBER = __LINE__ - BEGIN - 1 
}; 

auto const TEST_SIZE = TEST::NUMBER; 
+0

聰明!當然,不能有任何評論或不尋常的間距,對於真正大的源文件,底層的值類型可能會比其他的更大。 – 2016-09-05 00:46:38

+0

@Kyle Strand:存在這個問題:使用char,你也有超過256個枚舉器。但編譯器有很好的方式來通知你截斷等 __LINE__是一個整數字面值,並使用#line有限制[1,2147483647] – UglyCoder 2016-09-06 18:35:15

+0

啊,好的。儘管如此,即使一個本來是「short」的枚舉可能會碰到「int」,例如當做統一建設。 (雖然我認爲這與統一構建相比是一個問題,但與你提出的技巧相比)。 – 2016-09-06 19:55:26

6
constexpr auto TEST_START_LINE = __LINE__; 
enum class TEST { // Subtract extra lines from TEST_SIZE if an entry takes more than one 
    ONE = 7 
    , TWO = 6 
    , THREE = 9 
}; 
constexpr auto TEST_SIZE = __LINE__ - TEST_START_LINE - 3; 

這是從UglyCoder's answer三種方式產生,但它提高。

  • 裏有type_safe枚舉(BEGINSIZE)沒有多餘的元素(Cameron's answer也有這個問題。)
    • 編譯器不會抱怨他們是從一個switch語句缺失(一個顯著問題)
    • 它們不能無意中傳遞給需要枚舉的函數。 (不是一個普遍的問題)
  • 它不需要鑄造使用。 (Cameron's answer也有這個問題。)
  • 減法不會混淆enum類類型的大小。

它保留UglyCoder's優於Cameron's answer的優點是可以爲枚舉器賦予任意值。

一個問題(與UglyCoder共享,但不與Cameron共享)是它使新行和註釋顯着......這是意想不到的。所以有人可以添加一個空格或評論的條目,而不需要調整TEST_SIZE的計算。

1

您也可以考慮static_cast<int>(Example::E) + 1,它消除了額外的元素。

+2

這個答案對於這個特定的編程問題是正確的,但是一般來說遠非優雅和容易出錯。這個枚舉可以在將來用新的值進行擴展,以取代'Example :: E'作爲枚舉中的最後一個值。即使情況並非如此,「Example :: E」的文字值可能會改變。 – Matthias 2017-05-15 14:58:11

2

有基於X一招() - 宏:圖像,您有以下枚舉:

enum MyEnum {BOX, RECT}; 

格式化它:

#define MyEnumDef \ 
    X(BOX), \ 
    X(RECT) 

然後將下面的代碼定義枚舉類型:

enum MyEnum 
{ 
#define X(val) val 
    MyEnumDef 
#undef X 
}; 

和下面的代碼計算枚舉元素的數目:

template <typename ... T> void null(T...) {} 

template <typename ... T> 
constexpr size_t countLength(T ... args) 
{ 
    null(args...); //kill warnings 
    return sizeof...(args); 
} 

constexpr size_t enumLength() 
{ 
#define XValue(val) #val 
    return countLength(MyEnumDef); 
#undef XValue 
} 

... 
std::array<int, enumLength()> some_arr; //enumLength() is compile-time 
std::cout << enumLength() << std::endl; //result is: 2 
... 
相關問題