2013-06-19 6 views
0

Учитывая класс перечислимого класса C++ 11, существует ли какой-либо шаблон или другой конструктор для повторения во время компиляции по множеству всех счетчиков? Можно ли определить шаблон, например. инициализировать массив со всеми возможными значениями этого типа перечисления?Последовательность перечислителей во время компиляции

+0

Вы можете перевернуть свой собственный тип перечисления с помощью класса шаблонов varadic и пакетов параметров, начиная с класса 'template Enum', но это не очень хорошо. C++ нуждается в лучшем отражении, и есть рабочая группа, пытающаяся решить эту проблему. –

ответ

3

Одним из альтернативных способов является использование препроцессора.

#define ITERATE_MY_ENUM(_) \ 
    _(A,) \ 
    _(B, =3) \ 
    _(C,) \ 
    _(D, =10) 

enum MyEnum { 
    #define DEFINE_ENUM_VALUE(key, value) key value, 

    ITERATE_MY_ENUM(DEFINE_ENUM_VALUE) 

    #undef DEFINE_ENUM_VALUE 
}; 

void foo() { 
    MyEnum arr[] = { 
    #define IN_ARRAY_VALUE(key, value) key, 

    ITERATE_MY_ENUM(IN_ARRAY_VALUE) 

    #udnef IN_ARRAY_VALUE 
    }; 
} 

Некоторые считают его уродливым, но он по-прежнему сохраняет код DRY.

+0

Я думал об использовании препроцессора для этого, но мой подход был бы намного более привлекательным, используя несколько макросов повышения.Ваше решение выглядит намного проще для чтения и намного более легким. Должна быть возможность изменить код таким образом, чтобы 'value' включал' = ', так что вы можете оставить значение пустым, если вы хотите, чтобы поведение с автоматическим приращением для некоторых ключей. Очевидно, массив следует указывать в терминах ключей. Вы хотите изменить свой код? – MvG

+0

Хорошо, внесенные изменения. – zah

1

Нет, такой вещи нет. Также обратите внимание, что тип перечисления может содержать не только значения счетчиков по закону, но и любые их комбинации OR-ed вместе (смутно говоря).

Возможно, вы устранили проблему, используя простой генератор кода.

Reflecting comment: Here - хорошее резюме изменений в C++ 11 относительно перечня классов. Те, которые касаются неявных преобразований, контроль над базовым типом, определение имен, но не изменение фундаментальной природы. Перечислители по-прежнему просто близки к литералам без видимых связей. То, о чем вы просите, потребует отчасти отражений, AFAIK еще не на горизонте.

+1

Я не уверен, что часть ответа ИЛИ верна. На самом деле я совершенно уверен, что это наоборот. Объект типа перечисления может удерживать только один из счетчиков, при этом все остальное является неопределенным поведением. Код 'enum E {ONE = 1, TWO = 2}; E e = ОДИН | ДВА; switch (e) {case ONE: cout << "1"; ломать; case TWO: cout << "2"; ломать; default: cout << "other"; }; 'может вообще ничего не печатать (т. е. компилятору разрешено оптимизировать ветку« по умолчанию », так как все допустимые значения« e »имеют свой собственный случай. –

+0

3 является вполне допустимым значением для этого перечисления –

+0

I знайте, что это совмещение значений справедливо для старых счетчиков enum, но спокойно надеялось, что 'enum class' может избавиться от этого. В любом случае перечисление всех явно названных перечислений будет в порядке. Просто подсчет счетчиков будет в порядке : до тех пор, пока никто не назначает явные значения, можно использовать приведения, чтобы превратить экземпляры базового типа в допустимые значения. – MvG