Хорошо, я немного сыт по горло этой проблемой (некоторые из моих перечислений почти 100 пунктов)
поэтому я решил заняться этим с помощью генерации кода, которая, возможно, не является чашей чая для всех, но я понял, что на самом деле это не такая уж большая проблема.
В основном я выбрал Python Cog , который позволяет мне вставлять фрагменты Python в комментарии в моих файлах .h и .cpp и автоматически генерировать код. Я использую его в основном как действительно умную, обязательную систему макросов:
я добавил следующее к 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]]]
Затем я добавил вызов Cog на этапе предварительной сборки 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]]]
Итак, теперь моя проверка перечисления заключается в том, чтобы убедиться, что генерация кода (запускаемая во время компиляции) выполнена правильно