﻿# V719\. The switch statement does not cover all values of the enum\.

Анализатор обнаружил подозрительный оператор 'switch'\. Выбор варианта осуществляется по переменной enum\-типа\. При этом рассмотрены не все возможные варианты\.

Поясним это на примере:

```cpp
enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
}
```

Перечисление TEnum содержит 6 именованных констант\. Но в операторе 'switch' используется только 5 из них\. Высока вероятность, что это ошибка\.

Такая ошибка часто возникает в ходе рефакторинга\. В 'TEnum' добавили константу 'F"\. После этого какие\-то 'switch' поправили, а про какие\-то забыли\. В результате, значение 'F' начинает обрабатываться неправильно\.

Анализатор предупредит о том, что константа 'F' не используется\. И тогда программист может исправить оплошность:

```cpp
switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
  case F: Y(66); break;
}
```

Анализатор выдает предупреждение далеко не всегда, когда в 'switch' используется не все константы из перечисления\. Иначе, было бы слишком много ложных срабатываний\. Действует целый ряд исключений эмпирического типа\. Основные:

* Есть default\-ветка;
* В перечислении всего 1 или 2 константы;
* В switch не используется более чем 4 константы;
* Отсутствующая константа содержит в имени: None, Unknown и т\.п\.
* Отсутствующая константа самая последняя в enum и содержит в имени "end", "num", "count" и т\.п\.

Пользователь может сам задать список имён, которые обозначают последний элемент в перечислении\. В этом случае анализатор не использует список имён по умолчанию, такие как "num" или "count"\. Будут использованы только имена, указанные пользователем\. Комментарий, управляющий поведением диагностики V719:

```cpp
//-V719_COUNT_NAME=ABCD,FOO
```

Вы можете разметить этот комментарий в одном из файлов, включаемый во все другие\. Например, в [StdAfx\.h](https://pvs-studio.ru/ru/blog/posts/cpp/0265/)\.



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

С одной стороны, анализатору нельзя ругаться если константы не используются, но при это есть 'default'\. Будет слишком много ложных срабатываний и пользователи просто будут отключать эту диагностику\. С другой стороны, весьма типовой ситуацией является, когда в 'switch' следует рассмотреть все варианты, а ветка 'default' используется для отлова аварийных ситуаций\. Пример:

```cpp
enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
  default:
    throw MyException("Ай! Забыли рассмотреть один из вариантов!");
}
```

Ошибка может быть обнаружена только на этапе исполнения\. Естественно есть желание отловить эту ситуацию и с помощью анализатора\. В наиболее ответственных местах кода можно поступить следующим образом:

```cpp
enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
  #ifndef PVS_STUDIO
  default:
    throw MyException("Ай! Забыли рассмотреть один из вариантов!");
  #endif
}
```

Используется [предопределённый макрос PVS\_STUDIO](https://pvs-studio.ru/ru/docs/manual/0020/)\. Этот макрос отсутствует при компиляции\. Поэтому при компиляции исполняемого файла ветка 'default' остается на своём месте и в случае ошибки возникнет исключение\.

При проверке кода с помощью PVS\-Studio макрос PVS\_STUDIO определён и поэтому анализатор не увидит default\-ветку\. Поэтому он проверит 'switch', обнаружит что не используется константа 'F' и выдаст предупреждение\.

Исправленный вариант кода:

```cpp
switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
  case F: Y(66); break;
  #ifndef PVS_STUDIO
  default:
    throw MyException("Ай! Забыли рассмотреть один из вариантов!");
  #endif
}
```

Описанный подход не очень красив\. Однако, если вы очень переживаете за какой\-то 'switch' и хотите максимально защитить его, то этот способ вполне подходит\.