Spec-Zone.ru › C++

assert

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

Параметры

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

Примечания

Поскольку 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>
// uncomment to disable assert()
// #define NDEBUG
#include <cassert>

// Use (void) to silence unused warnings.
#define assertm(exp, msg) assert((void(msg), exp))

int main()
{
    assert(2 + 2 == 4);
    std::cout << "Checkpoint #1\n";
    
    assert((void("void helps to avoid 'unused value' warning"), 2 * 2 == 4));
    std::cout << "Checkpoint #2\n";
    
    assert((010 + 010 == 16) && "Yet another way to add an assert message");
    std::cout << "Checkpoint #3\n";
    
    assertm((2 + 2) % 3 == 1, "Success");
    std::cout << "Checkpoint #4\n";
    
    assertm(2 + 2 == 5, "Failed"); // assertion fails
    std::cout << "Execution continues past the last assert\n"; // No output
}

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

Checkpoint #1
Checkpoint #2
Checkpoint #3
Checkpoint #4
main.cpp:23: int main(): Assertion `((void)"Failed", 2 + 2 == 5)' failed.
Aborted

Отчёты об ошибках

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

DR Применён к Опубликованное поведение Корректное поведение
LWG 2234 C++11 assert нельзя было использовать в константном выражении можно использовать

См. также

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

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/error/assert

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API