enum E { A, B, C };
int getE();
switch((E)getE())
{
case A: handleA(); break;
case C: handleC(); break; // ой, потеряли B!default: oops("Value outside enum!");
}
Как сделать то же самое, но чтобы компилятор ругался, если я не обработаю часть значений enum? Если я выброшу default, то предупреждения будут («enumeration value ‘B’ not handled in switch»), но потеряется поведение по умолчанию. Можно вместо break сделать goto, а сразу за switch разместить код обработки ошибки. А как сделать по-человечески?
RO>Как сделать ... чтобы компилятор ругался, если я не обработаю часть значений enum?
Вот не понимаю, какой смысл в этом предупреждении. Меня оно в свое время ужасно раздражало, потому что я просто так енумов в свитче не пропускаю. А если там больше 10 вариантов, то надо пересмотреть способ обработки, ибо такой ужасный огромный свитч очень трудно поддерживать.
Здравствуйте, Roman Odaisky, Вы писали:
RO>Как сделать то же самое, но чтобы компилятор ругался, если я не обработаю часть значений enum? Если я выброшу default, то предупреждения будут («enumeration value ‘B’ not handled in switch»), но потеряется поведение по умолчанию. Можно вместо break сделать goto, а сразу за switch разместить код обработки ошибки. А как сделать по-человечески?
Как вариант вынести в отдельную функцию:
void handle()
{
switch((E)getE())
{
case A: handleA(); return;
case C: handleC(); return;
}
oops("Value outside enum!");
assert(false);
}
Здравствуйте, remark, Вы писали:
RO>>Как сделать то же самое, но чтобы компилятор ругался, если я не обработаю часть значений enum? Если я выброшу default, то предупреждения будут («enumeration value ‘B’ not handled in switch»), но потеряется поведение по умолчанию. Можно вместо break сделать goto, а сразу за switch разместить код обработки ошибки. А как сделать по-человечески?
R>Как вариант вынести в отдельную функцию: R>
Это тот же goto, только в профиль. Меня еще что смущает: вдруг будет переполнение при приведении к типу enum? Оно здесь, по сути, не требуется, оно только для ворнингов.
(Qt любит в самых неожиданных местах возвращать -1 и смотреть, что из этого получится. Я тут перешел на 4.4, теперь эти неожиданные места обнаруживаются в более других неожиданных местах, чем раньше, а мне ловить.)
Здравствуйте, Roman Odaisky, Вы писали:
RO>Это тот же goto, только в профиль. Меня еще что смущает: вдруг будет переполнение при приведении к типу enum? Оно здесь, по сути, не требуется, оно только для ворнингов.
RO>(Qt любит в самых неожиданных местах возвращать -1 и смотреть, что из этого получится. Я тут перешел на 4.4, теперь эти неожиданные места обнаруживаются в более других неожиданных местах, чем раньше, а мне ловить.)
Может тогда как-то так:
enum E
{
E1 = 1;
E2 = 2;
E4 = 4;
E100 = 100;
};
E convert_to_E(int e)
{
if (e < 1 || (e > 4 && e != 100) || e == 3)
oops("Value outside enum!");
return (E)e;
}
switch(convert_to_E(getE()))
{
case A: handleA(); break;
case C: handleC(); break;
}
RO>enum E { A, B, C };
RO>int getE();
RO>switch((E)getE())
RO>{
RO>case A: handleA(); break;
RO>case C: handleC(); break; // ой, потеряли B!
RO>default: oops("Value outside enum!");
RO>}
RO>
Может так ?
E checkE(int e)
{
switch(e)
{
case A:
case B:
case C:
return static_cast<E>(e); // Проверено. Переполнений нет.
}
oops("Value outside enum!");
return static_cast<E>(e); // Это не валидно, может переполнится, лучше oops кинет
}
void F()
{
switch(/*E e =*/ checkE(getE()))
{
case A: handleA(); break;
case C: handleC(); break;
} // ой, потеряли B!
}
PS: не проверял, в Студии такого ворнинга, похоже, нет.
template< int valueA, typename handlerA,
int valueB, typename handlerB,
int valueC, typename handlerC >
struct Enum
{
enum E { a = valueA, b = valueB, c = valueC };
static void handle( E e )
{
switch( e )
{
case a: handlerA::handle(); break;
case b: handlerB::handle(); break;
case c: handlerC::handle(); break;
default: assert( !"unhandled" );
}
}
};
struct handleA { static void handle() {} };
struct handleB { static void handle() {} };
struct handleC { static void handle() {} };
typedef Enum< 1, handleA,
2, handleB,
3, handleC > Handler;
...
Handler::handle( Handler::a );
не укажешь значение/обработчик — компилер ругнется
ps. (На всякий случай) не пиши так, внимательно прочекать switch на предмет проверки всех енумов будет правильней и в будущем легче для понимания коллег, которым твой код перейдет. ИМХО