In C++26, contracts (long-form contract assertions) fill the main role of runtime asserts, without using preprocessor macros (which assert does). It introduces three new keywords:

  • contract_assert functions essentially the same as an assert, but is defined such that it doesn’t rely on macros to function.
  • pre is a pre-condition associated with a function. post is a post-condition associated with a function. The benefit with both of these is that they’re in the function signature, which codifies conditions that used to be implicit. Great for readability and for tools.

Pre C++26 asserts relied on conditional compilation behaviour, such that assert could’ve been defined differently on debug and release mode (like #ifdef DBG). To help bridge this gap, contracts are evaluated based on certain semantics:1

  • Ignore — no runtime checks. Like release-mode asserts.
  • Observe — will check at runtime, but will not terminate. A diagnostic can be produced.
  • Enforce — will check, and can terminate. Like debug-mode asserts.
  • Quick-enforce — will check, and can terminate. Less overhead?

Upon a contract violation, we enter a contract violation handler. This can be defined by the programmer, so it “enables hooking into … existing logging/alerting mechanisms”!2

Footnotes

  1. Contract assertions (since C++26) - cppreference.com

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