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_assertfunctions essentially the same as anassert, but is defined such that it doesn’t rely on macros to function.preis a pre-condition associated with a function.postis 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