9

我有一些枚举类

enum class Foo { A=1, B=18 , Z=42 };

我想检查是否可以将某个整数转换为Foo. 这样做的理想方法是什么?这是用于运行时检查(在编译时整数未知)

显然,我可以通过艰难的方式做到这一点(编写一个bool CheckEnum(Foo);带有大开关的函数,对于除默认情况外的所有情况都返回 true),但我希望有一种更优雅的机制来避免这么多的编写。MPL 或Boost.Preprocessor将是一个完全可以接受的解决方案,但遗憾的是我对其中一个知之甚少

4

3 回答 3

2

解决此问题的方法是放弃枚举,并用一些使用XMACRO创建的数组替换它。

于 2011-11-27T16:16:15.100 回答
0

没有“理想”的方式来做到这一点。所有方法都必须涉及一些手工工作。

您需要创建一个包含所有可接受值的数据结构。然后使用您需要的运行时值搜索该数据结构。A std::setorstd::unordered_set足以满足此目的。

您的主要困难在于维护该列表,因为每次更改您的enum class.

于 2011-11-22T03:56:55.707 回答
0

好的,我有点厌倦了这个问题(我的一些枚举有近 100 个项目)所以我决定通过代码生成来解决它,这可能不是每个人的一杯茶,但我意识到这真的不是这么大的事。

基本上我选择了Python Cog,它允许我在 .h 和 .cpp 文件的注释中嵌入 python 片段并自动生成代码。我基本上像一个非常聪明的命令式宏系统一样使用它:

我添加了以下内容Test.h

/*[[[cog
#----------- definitions

import cog

def createCategoryConstants( enumVar , bitShift ):
    categoryIndex = 0
    for cat in enumVar:
        cog.outl(' const unsigned int %s_op_mask = (%d << %d); ' %(cat[0] , categoryIndex , bitShift))
        categoryIndex += 1
    cog.outl('\n\n')

def createMultiCategoryEnum( enumVar , enumTypename ):
    cog.outl(' enum class %s { ' % enumTypename )
    categoryIndex = 0
    for i in enumVar:
        itemIndex = 0
        catName = 'NotExpected'
        remainingCategories = len(enumVar)- categoryIndex - 1
        for j in i:
            if (itemIndex == 0):
                catName = j
                itemIndex = 1
                continue
            enumItemIndex = 0
            for enumItem in j:
                remainingEnums = len(j) - enumItemIndex - 1
                currentLine = ' %s = %s_op_mask | %d ' %(enumItem, catName, enumItemIndex)
                if (remainingCategories != 0 or remainingEnums != 0):
                    currentLine += ' , '
                cog.outl(currentLine)
                enumItemIndex += 1
            itemIndex += 1
        cog.outl('') #empty line to separate categories
        categoryIndex += 1
    cog.outl(' };\n\n')

def createIndexFromEnumFunction( enumVar , enumTypename , functionName ):
    cog.outl('uint32_t %s(%s a) { \n switch (a)\n {' % (functionName , enumTypename) )
    absoluteIndex = 0
    for cat in enumVar:
        elemInCat = 0
        for i in cat:
          if elemInCat != 0:
             for enumItem in i:
               cog.outl('case %s:' % enumItem)
               cog.outl(' return %d; \n' % absoluteIndex)
               absoluteIndex += 1
          elemInCat += 1
    cog.outl(' } \n } \n\n ')


def createMultiEnum( enumVar , enumTypename ):
    createCategoryConstants( enumVar , 4)
    createMultiCategoryEnum( enumVar , enumTypename )
    createIndexFromEnumFunction( enumVar , enumTypename , 'FromOpToIndex' )

#------------- generation

multiEnum =[ ['CatA', ['A1', 'A2' , 'A3_foo']] , ['CatSuper8' , ['Z1_bla' , 'Z10' , 'Z11']] ]

createMultiEnum( multiEnum , 'multiFooEnum')

]]]*/
//[[[end]]]

然后我在我的 Makefile 预构建步骤中添加了 cog 调用:

.build-pre:
# Add your pre 'build' code here...
    python /usr/local/bin/cog.py -I../../../tools/cog/ -r *.h

结果显示在下面:

]]]*/
 const unsigned int CatA_op_mask = (0 << 4); 
 const unsigned int CatSuper8_op_mask = (1 << 4); 



 enum class multiFooEnum { 
 A1 = CatA_op_mask | 0  , 
 A2 = CatA_op_mask | 1  , 
 A3_foo = CatA_op_mask | 2  , 

 Z1_bla = CatSuper8_op_mask | 0  , 
 Z10 = CatSuper8_op_mask | 1  , 
 Z11 = CatSuper8_op_mask | 2 

 };


uint32_t FromOpToIndex(multiFooEnum a) { 
 switch (a)
 {
case A1:
 return 0; 

case A2:
 return 1; 

case A3_foo:
 return 2; 

case Z1_bla:
 return 3; 

case Z10:
 return 4; 

case Z11:
 return 5; 

 } 
 } 


//[[[end]]]

所以,现在我的枚举验证是关于确保代码生成(在编译时调用)正确完成

于 2011-11-27T16:11:21.707 回答