2017-10-21 249 views
1

我已經相當確定要提出的問題是不可能的,除非創建自己的枚舉類型,但我認爲它值得將它放在那裏以防萬一我錯過了一些東西,因爲它會簡化我在工作和自己的項目中經常遇到的情況。基本上,我想要一個返回枚舉類中所有枚舉列表的通用方法,或者至少返回所有正枚舉的一般方法,直到一個枚舉特定的,但另有預先確定的點。好吧,最後一個想法很混亂,所以我會發布我的意思下面的僞代碼...確定枚舉類中的枚舉數(或任何枚舉類中的特定枚舉值)

一種設置特定枚舉「密鑰?」的方法用來返回正數枚舉的數量,直到給定鍵:

template<typename EnumType> 
std::vector<EnumType> getFullEnumList() 
{ 
    std::vector<EnumType> fullEnumList; 

    for (enumIndex = 0; enumIndex < EnumType::NumEnums; enumIndex++) 
     fullEnumList.push_back(static_cast<EnumType>(enumIndex)); 

    return fullEnumList; 
} 

我猜這不會是一個實際的東西來實現上面的陳述,因爲編譯器不關心我我已經調用了每個枚舉類的值,只有它的值和類的類型......所有編譯器在最終編譯階段處理的權利?

我的第一個想法,我想會涉及某種:

EnumClass::size() 

...功能,這點我已經知道是不存在的,但我目前不知道有足夠的瞭解枚舉的細節類來理解爲什麼這將不可能實現在未來的C++迭代......我猜這是不可能的,或者這將是在大多數枚舉類用例中不希望的額外開銷,否則他們會實現它幾年前...

但是爲了縮小我的實際問題,在額外的知識塊之上,你們可以提供給我關於t他以上的沉思,有沒有一些通用的方式來做到這一點,我沒有想到?

乾杯提前爲您的見解,

皮特

+1

你的問題是不是僅僅讓普查員的數量更大。不要忘記枚舉器不必命名連續值('enum foo {bar = 22,baz = 420000};') – StoryTeller

+0

沒有將設施指定爲C++本身的一部分。您可以編寫一個程序來解析枚舉類型的定義,並輸出源代碼以生成列表。該程序需要處理枚舉類型中的值不連續,給定數值的名稱不止一個等等。如果您真的想要,該程序還可以輸出將枚舉值映射到字符串的代碼。 – Peter

+0

聽起來像你想要一些編譯時反射 - 哪些C++沒有(還)。 –

回答

0

如果你有一些常規的枚舉(只是sequental值,而不是標誌),你可以快速achive,通過使用邊界值:

enum t_MyEnum 
{ 
    enum_begin 

, monday = enum_begin 
, tuesday 
... 
, sunday 

, enum_end 
, enum_items_cout = enum_end - enum_begin 
}; 

更靈活的方式是實現一些枚舉類型特徵。

// traits 
template<typename TEnum> class t_Integral 
{ 
    public: using t_Type = int; 
}; 

template<typename TEnum> class t_FirstItem; 

template<typename TEnum> class t_LastItem; 

template<typename TEnum> class t_ItemsCount 
{ 
    public: static constexpr const ::std::size_t value 
    { 
     static_cast<::std::size_t> 
     (
      static_cast<typename t_Integral<TEnum>::t_Type>(t_LastItem<TEnum>::value) 
      - 
      static_cast<typename t_Integral<TEnum>::t_Type>(t_FirstItem<TEnum>::value) 
      + 
      1 
     ) 
    }; 
}; 

// enum 
enum class t_MyEnum 
: ::std::uint16_t 
{ 
    monday 
, tuesday 
... 
, sunday 
}; 

// specialize traits (can also be done to third-party enums) 
template<> class t_Integral<t_MyEnum> 
{ 
    public: using t_Type = ::std::uint16_t; 
}; 

template<> class t_FirstItem<t_MyEnum> 
{ 
    public: static constexpr const auto value{t_MyEnum::monday}; 
}; 

template<> class t_LastItem<t_MyEnum> 
{ 
    public: static constexpr const auto value{t_MyEnum::sunday}; 
}; 

// now we have a generic way to get enum items count and can use it somehow... 
::std::array< int, t_ItemsCount<t_MyEnum>::value > items; 

Enum類型性狀可以定義像枚舉項名稱的東西(字符串)和相應轉換功能,通過樣枚舉的分離(「順序枚舉」,「疏枚舉」,「位標誌枚舉」),迭代通過枚舉值,空值等。

+0

好 - 特別是如果你使用(可變的)宏來定義你需要的所有專業化... – davidbak

0

如果您不介意依賴關係,那麼可以通過使用Qt框架以簡單的方式解決此問題。

看一看QMetaEnum,尤指。功能keyCount

用途由該接受的答案的StackOverflow的question描述:基本上,你必須將Q_ENUM(myEnum)宏附加到您的枚舉定義myEnum在類myEnumClass

然後你通過相應QMetaEnum對象調用QMetaEnum myMetaEnum = QMetaEnum::fromType<myEnumClass::enumName>();

2

如果您使用具有連續值的枚舉,則可以使用這個老技巧。

定義Max(和一個可選的Min)每個枚舉你有值:

enum class MyEnum 
{ 
    Sunday, 
    Monday, 
    Tuesday, 
    Wednesday, 
    Thursday, 
    Friday, 
    Saturday, 
    Max, 
    Min = Sunday // (Optional, see following notes) 
}; 

定義你的枚舉法如下:

template<typename EnumType> 
std::vector<EnumType> 
getFullEnumList(int from = (int)EnumType::Min, int to = (int)EnumType::Max) 
{ 
    std::vector<EnumType> fullEnumList; 

    for (auto enumIndex = from; enumIndex < to; enumIndex++) 
     fullEnumList.push_back(static_cast<EnumType>(enumIndex)); 

    return fullEnumList; 
} 

採用EnumType::MinEnumType::Max爲默認值將保護此方法對於沒有正確定義的Enum類型的調用。

注:如果所有枚舉使用積極值而已,就可以避免Min的decleration和使用int from = 0getFullEnumList

,並使用此方法平凡:

auto enumsList = getFullEnumList<MyEnum>(); 
-- OR -- 
auto enumsList = getFullEnumList<MyEnum>(2, 4); 
+0

這是傳統的方式 - 明確的最小,最大元素。 C++可以在這個領域使用一些額外的語言工具。 Ada'83具有第一,最後,最小,最大,pred,succ,pos,val,image(→字符串)和value(字符串→)的屬性。不知道爲什麼我們不能擁有它們。 (根據C++理念很容易實現它們:除非使用,否則不需要花費。) – davidbak