2017-10-21 165 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