9

私はいくつかの列挙型クラスを持っています

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

整数をに変換できるかどうかを確認したいFoo。これを行うための理想的な方法は何でしょうか?これは実行時チェック用です(整数はコンパイル時にまだ不明です)

明らかに私はこれを難しい方法で行うことができます(bool CheckEnum(Foo);デフォルトを除くすべての場合にtrueを返す大きなお尻のスイッチで関数を書く)が、私はそれほど多くの書き込みを回避するよりエレガントなメカニズムを望んでいました。MPLまたはBoost.Preprocessor完全に許容できるソリューションですが、残念ながらその1つについてはほとんど知りません。

4

3 に答える 3

2

この問題の解決策は、列挙型を破棄し、 XMACROを使用して作成されたいくつかの配列に置き換えることです。

于 2011-11-27T16:16:15.100 に答える
0

それを行うための「理想的な」方法はありません。すべての方法で、手作業が必要になります。

許容可能なすべての値を含むデータ構造を作成する必要があります。次に、必要なランタイム値を使用してそのデータ構造を検索します。この目的には、std::setまたはstd::unordered_setが適切です。

を変更するたびに更新する必要があるため、主な問題はそのリストを維持することですenum class

于 2011-11-22T03:56:55.707 に答える
0

わかりました、私はこの問題に少しうんざりしています(私の列挙型のいくつかはほぼ100アイテムです)ので、私はコード生成でそれに取り組むことにしました、それはみんなのお茶ではないかもしれません、しかし私はそれが本当にないことに気づきましたそのような大したこと。

基本的に私はPythonCogを選びました。これにより、.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のビルド前の手順で歯車の呼び出しを追加しました。

.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 に答える