Evgenii Legotckoi
2 января 2018 г. 15:33

С++ - Урок 012. static_assert, проверка на ошибки во время компиляции

Содержание

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

Использование static_assert будет выглядеть следующим образом.

  1. static_assert(4<=sizeof(int), "integers are too small"); // проверка размера integer

Синтаксис будет следующим static_assert(A, B); где

  • A - это условие, при котором будет выбрасываться ошибка в том случае, если A равно false
  • B - это текст сообщения об ошибке

Применение

static_assert может быть полезен при использовании констант и константных выражений, которые вычисляются на этапе компиляции.

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

  1. constexpr double C = 299792.458; // km/s, скорость света
  2.  
  3. void f(double speed)
  4. {
  5. const double local_max = 160.0/(6060); // 160 km/h == 160.0/(60*60) km/s
  6. static_assert(speed<C,"can't go that fast"); // error: speed должна быть константой
  7. static_assert(local_max<C,"не может двигаться быстрее"); // OK
  8. }

Также ещё можно использовать данную проверку в ключевых местах для перечислений. Например, дано такое перечисление.

  1. enum Types
  2. {
  3. E_BEGIN_TYPES,
  4. E_A = E_BEGIN_TYPES,
  5. E_B,
  6. E_C,
  7. E_D,
  8. E_END_TYPES = E_D
  9. };

И есть следующий метод или функция в каком-то месте кода

  1. QString getStandardMessage(Types type)
  2. {
  3. static_assert(E_END_TYPES == 3, "Need to implement method for new type");
  4.  
  5. switch (type)
  6. {
  7. case E_A: return "Type A";
  8. case E_B: return "Type B";
  9. case E_C: return "Type C";
  10. case E_D: return "Type D";
  11. default: return "Type is not implemented";
  12. }
  13. }

В данном случае мы знаем, что самые последние перечисления, то есть E_D или E_END_TYPES будут равны 3. И исключение во время компиляции выброшено не будет. Но как только будет добавлен новый участник данного перечисления.

  1. enum Types
  2. {
  3. E_BEGIN_TYPES,
  4. E_A = E_BEGIN_TYPES,
  5. E_B,
  6. E_C,
  7. E_D,
  8. E_E, // Новый участник перечисления
  9. E_END_TYPES = E_E
  10. };

То static_assert выбросит ошибку, которая будет означать, что мы забыли поправить данный метод. Исправление будет выглядеть следующим образом.

  1. QString getStandardMessage(Types type)
  2. {
  3. static_assert(E_END_TYPES == 4, "Need to implement method for new type");
  4.  
  5. switch (type)
  6. {
  7. case E_A: return "Type A";
  8. case E_B: return "Type B";
  9. case E_C: return "Type C";
  10. case E_D: return "Type D";
  11. case E_E: return "Type E";
  12. default: return "Type is not implemented";
  13. }
  14. }

В данном методе мы добавим реализацию кода для типа E_E, а также поправим сам static_assert, чтобы он учитывал количество участников перечисления с новым участником.

Рекомендуемые статьи по этой тематике

По статье задано0вопрос(ов)

1

Вам это нравится? Поделитесь в социальных сетях!

Комментарии

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