Asserts are a feature in most programming languages. They primarily function as checks to ensure runtime invariants aren’t violated, i.e., a certain function isn’t running in an unexpected state it isn’t designed for.

Asserts help ensure functional safety, where we incrementally gain confidence that the system meets its requirements. Each individual assert provides a new runtime invariant.1 Asserts document the assumed invariants of a given snippet of code.2

Language-specific

In C++

C++ inherited C’s assert structure, where we take:

  • Argument 1: a predicate
  • Argument 2: an optional output message

Runtime asserts can be done via the cassert library:

int x = fork();
assert(x != -1, "fork() has failed!");

As in C, assert behaviour depends on how the program is compiled. It may terminate, or it may continue silently. This assert is defined as a preprocessor macro.

Compile-time asserts are built into the language with static_assert as of C++11. Failed asserts will stop the program from being compiled. Predicates also need to be evaluable at compile-time, i.e., constexpr.

constexpr int x = -1;
static_assert(x > 0); // fails!

It is best to use static_assert in the source file. If in the header, it will be evaluated for each #included instance.

C++26 will introduce contract assertions (or just contracts), which are a new non-macro functional safety mechanism at runtime. contract_assert is a keyword. It behaves the same as the old assert macros. It also introduces pre-conditions and post-conditions in the function’s interface. Incredible!

Footnotes

  1. The Joy of C++26 Contracts - Myths, Misconceptions & Defensive Programming - Herb Sutter

  2. “They arguably have the best complexity / effectiveness ratio.” in C++ Coding Standards by Herb Sutter and Andrei Alexandrescu