Подтвердить что ты не робот

Compile-time assert, когда не все значения перечисления обрабатываются в инструкции switch в С++

Я хотел бы получить предупреждение или ошибку компилятора, когда не все возможные значения перечисления обрабатываются в инструкции switch. Конечно, я могу добавить случай по умолчанию с утверждением и (в конечном итоге) получить ошибку во время выполнения. Но я бы хотел получить ошибку во время компиляции.

Я не уверен, что это вообще возможно с С++, но, возможно, кто-то знает трюк...

Изменить: Использование -Wswitch представляется решением для GCC. Есть ли что-то подобное для VS2010? (Я не использую GCC).

Edit2: Хорошо, я нашел решение для VС++ (VS2010):

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

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

4b9b3361

Ответ 1

Вы не указали, какой компилятор вы используете. Если вы используете GCC, вы можете получить это бесплатно, просто включив -Wswitch (который автоматически включается -Wall).

Ответ 2

Если вы используете g++, с -Wall, вы получите его.

Например, это:

enum Abc
{
  A =1,
  B,
  C
};

Abc a = A;
switch( a )
{
 case A:
  break;
 case B:
  break;
}

будет вызывать предупреждение.

Но лучше использовать аргумент default с неудачным утверждением, потому что когда вы добавляете новое значение enum, вы должны изменить все файлы, в которых вы используете переключатель на этом перечислении.

Ответ 3

AFAIK нет обычного способа добиться того, что вы хотите с помощью MSVC. Есть трюки, чтобы делать подобные вещи, но они включают либо сложный шаблон voodoo, либо действительно жестокие макросы загадок.

Например, вместо определения вашего перечисления обычным способом выполните следующие действия:

#define MyEnumEntries(m) \
    m(A, 1) \
    m(B, 2) \
    m(C, 3) \

enum Abc {

    // the following will expand into your enum values definitions
#   define M_Decl(name, value) name = value,
    MyEnumEntries(M_Decl)
};

Теперь ваш коммутатор можно переписать следующим образом:

Abc a = A;

switch( a )
{
#define M_Goto(name, value) \
case value:
    goto label_##name;

MyEnumEntries(M_Goto)


case label_A:
    // TODO
    break;
case label_B:
    // TODO
    break;
}

Вышеуказанное не будет компилироваться, если вы не добавите запись переключателя label_... для всех значений перечисления.

Ответ 4

g++ делает это автоматически, если вы включаете все предупреждения с помощью -Wall.