Static assert — это механизм компилятора для генерации ошибок на этапе компиляции, если выражение (условие) не выполняется. Функционал был добавлен начиная с C++11 для облегчения программирования шаблонов и повышения качества кода.
История вопроса.
До появления static_assert программисты использовали финты вроде структуры с отрицательным размером массива (типа char arr[condition?1:-1];), что было менее читаемо и менее удобно для диагностики ошибок. Так возникла потребность в явной декларации ошибок времени компиляции с осмысленным сообщением.
Проблема.
В шаблонном программировании часто возникает необходимость ранней диагностики (например, запрет на создание объекта с неподходящим типом или параметром). Без статической проверки такие ошибки появлялись только на стадии компиляции конечного кода (иногда внезапной и плохо объяснённой ошибкой).
Решение.
Ключевое слово static_assert принимает булево выражение и строку сообщения. Если выражение ложно — компиляция завершится ошибкой с выводом сообщения.
Пример кода:
static_assert(sizeof(int) >= 4, "int must be at least 4 bytes"); template<typename T> void foo(const T& obj) { static_assert(std::is_copy_constructible<T>::value, "T must be copy-constructible"); }
Ключевые особенности:
Можно ли использовать static_assert без второго аргумента?
Да, начиная с C++17 второй аргумент является необязательным:
static_assert(sizeof(double) == 8); // сообщение будет по умолчанию
Выполняются ли static_assert выражения, если условие зависит от шаблонных параметров, но шаблон не инстанцируется?
Нет, static_assert срабатывает только если доходит до точки инстанциации, что позволяет применять проверки только для используемых шаблонов.
Можно ли использовать выражения времени выполнения (run-time) внутри static_assert?
Нет, выражение должно быть вычисляемым на этапе компиляции (constexpr). Если выражение не является constexpr — ошибка компиляции.
В коде использовали static_assert с выражением, вычисляемым только в рантайме (например, размер файла с чтением ввода), что вызвало непонятную ошибку компиляции во всей системе.
Плюсы:
Минусы:
Требуется гарантировать, что шаблон Matrix может создаваться только с Plain Old Data (POD) типами, исключая сложные структуры.
template<typename T> class Matrix { static_assert(std::is_pod<T>::value, "Matrix can be instantiated only for POD types"); // ... };
Плюсы:
Минусы: