Namespaces
Variants

assert

From cppreference.net
Определено в заголовочном файле <cassert>
Отключенное утверждение
(1)
#define assert(condition) ((void)0)
(до C++26)
#define assert(...)       ((void)0)
(начиная с C++26)
Включенное утверждение
(2)
#define assert(condition) /* unspecified */
(до C++26)
#define assert(...)       /* unspecified */
(начиная с C++26)

Определение макроса assert зависит от другого макроса, NDEBUG , который не определён стандартной библиотекой.

1) Если NDEBUG определён как имя макроса в точке исходного кода, где подключается <cassert> или <assert.h> , утверждение отключается: assert ничего не делает.
2) В противном случае утверждение активно:

assert проверяет свой аргумент (который должен иметь скалярный тип):

  • Если аргумент сравнивается как неравный нулю, дальнейших эффектов нет.
  • В противном случае, assert создаёт диагностическое сообщение в стандартном потоке ошибок и вызывает std::abort() .
(до C++26)

assert помещает диагностический тест в программы и раскрывается в выражение типа void . __VA_ARGS__ вычисляется и контекстно преобразуется в bool :

  • Если вычисление даёт true , дальнейших эффектов нет.
  • В противном случае, assert создаёт диагностическое сообщение в стандартном потоке ошибок и вызывает std::abort() .
(начиная с C++26)

Диагностическая информация имеет формат, определяемый реализацией, но она всегда включает следующие сведения:

  • текст condition
(до C++26)
  • #__VA_ARGS__
(начиная с C++26)
  • имя исходного файла (т.е., __FILE__ )
  • номер строки в исходном коде (т.е., __LINE__ )
  • имя охватывающей функции (т.е., __func__ )

Выражение assert ( E ) гарантированно является постоянным подвыражением , если выполняется одно из условий:

  • NDEBUG определено в точке, где assert последний раз определен или переопределен, или
  • E , контекстно преобразованное в bool , является постоянным подвыражением, которое вычисляется в true .
(начиная с C++11)

Содержание

Параметры

условие - выражение скалярного типа

Примечания

Поскольку assert является функционально-подобным макросом , запятые в аргументе, не защищённые круглыми скобками, интерпретируются как разделители аргументов макроса. Такие запятые часто встречаются в списках шаблонных аргументов и списковой инициализации:

assert(std::is_same_v<int, int>);        // error: assert does not take two arguments
assert((std::is_same_v<int, int>));      // OK: one argument
static_assert(std::is_same_v<int, int>); // OK: not a macro
std::complex<double> c;
assert(c == std::complex<double>{0, 0});   // error
assert((c == std::complex<double>{0, 0})); // OK
(до C++26)

Не существует стандартизированного интерфейса для добавления дополнительного сообщения к ошибкам assert . Переносимым способом включения такого сообщения является использование оператора запятой при условии, что он не был перегружен , либо использование && со строковым литералом:

assert(("There are five lights", 2 + 2 == 5));
assert(2 + 2 == 5 && "There are five lights");

Реализация assert в Microsoft CRT не соответствует стандартам C++11 и более поздним версиям, поскольку её базовая функция ( _wassert ) не принимает ни __func__ , ни эквивалентную замену.

Начиная с C++20, значения, необходимые для диагностического сообщения, также могут быть получены из std::source_location::current() .

Несмотря на то, что изменение assert в C23/C++26 формально не является отчётом о дефекте, комитет по стандартизации C рекомендует реализациям переносить это изменение в старые режимы.

Пример

#include <iostream>
// раскомментируйте для отключения assert()
// #define NDEBUG
#include <cassert>
// Используйте (void) для подавления предупреждений о неиспользуемых переменных.
#define assertm(exp, msg) assert((void(msg), exp))
int main()
{
    assert(2 + 2 == 4);
    std::cout << "Контрольная точка #1\n";
    assert((void("void помогает избежать предупреждения 'неиспользуемое значение'"), 2 * 2 == 4));
    std::cout << "Контрольная точка #2\n";
    assert((010 + 010 == 16) && "Еще один способ добавить сообщение assert");
    std::cout << "Контрольная точка #3\n";
    assertm((2 + 2) % 3 == 1, "Успех");
    std::cout << "Контрольная точка #4\n";
    assertm(2 + 2 == 5, "Неудача"); // утверждение не выполняется
    std::cout << "Выполнение продолжается после последнего assert\n"; // Вывода нет
}

Возможный вывод:

Контрольная точка #1
Контрольная точка #2
Контрольная точка #3
Контрольная точка #4
main.cpp:23: int main(): Assertion `((void)"Failed", 2 + 2 == 5)' failed.
Aborted

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
LWG 2234 C++11 assert could not be used in constant expression can be used

Смотрите также

contract_assert statement (C++26) проверяет внутреннее условие во время выполнения
static_assert declaration (C++11) выполняет проверку утверждений во время компиляции
вызывает аварийное завершение программы (без очистки)
(функция)
C documentation для assert