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

Contract assertions allow the programmer to specify properties of the state of the program that are expected to hold at certain points during execution.

Contents

[edit] Explanation

Contract assertions are introduced by function contract specifiers and contract_assert statements. Each contract assertion has a predicate , which is an expression of type bool.

[edit] Evaluating contract assertions

An evaluation of a contract assertion uses one of the following evaluation semantics:

Evaluation semantic Is a checking semantic Is a terminating semantic
ignore
observe Yes
enforce Yes Yes
quick-enforce Yes Yes

It is implementation-defined which evaluation semantic is used for any given evaluation of a contract assertion. The evaluation semantics can differ for different evaluations of the same contract assertion, including evaluations during constant evaluation.

If the “ignore” semantic is used, the evaluation of a contract assertion has no effect.

If a checking semantic is used, the evaluation E of a contract assertion determines the value of the predicate. It is unspecified whether the predicate is evaluated. If any of the following conditions is satisfied, a contract violation occurs:

There is an observable checkpoint CP that happens before E such that any other operation OP that happens before A also happens before CP.

int num = 0; void f() pre((num++, false));   f(); // Increment of “num” might not occur, even if a checking semantic is used

[edit] Handling contract violations

If a contract violation occurs in a context that is manifestly constant-evaluated:

If a contract violation occurs in a context that is not manifestly constant-evaluated:

[edit] Contract-terminated programs

When the program is contract-terminated , it is implementation-defined (depending on context) whether

[edit] Contract-violation handler

The contract-violation handler of a program is a function named ::handle_contract_violation:

| void handle_contract_violation( std::contracts::contract_violation ); | | (since C++26) (optionally noexcept) | | ------------------------------------------------------------------------ | | ----------------------------------- |

A definition of the contract-violation handler, called the default contract-violation handler , is provided by the implemenation (instead of a standard library header).

It is implementation-defined whether the contract-violation handler is replaceable. If the contract-violation handler is not replaceable, a declaration of a replacement function for the contract-violation handler is ill-formed, no diagnostic required.

When the contract-violation handler returns normally:

There is an observable checkpoint CP that happens after the contract-violation handler returns normally such that any other operation OP that happens after the contract-violation handler returns also happens after CP.

[edit] Handling exceptions from assertions

If the contract violation occurred because the evaluation of the predicate exited via an exception and the evaluation semantic is “observe” or “enforce”, the contract-violation handler is invoked from within an active implicit handler for that exception.

When the contract-violation handler returns normally:

The current exception can be inspected or rethrown within the contract-violation handler using std::current_exception().

[edit] Evaluate in sequence

To evaluate in sequence a list R of contract assertions:

  1. Construct a list of contract assertions S such that all following conditions are satisfied:
  1. Evaluate each element of S such that, if a contract assertion A precedes a contract assertion B in S, then the evaluation of A is sequenced before the evaluation of B.

void f(int i) { contract_assert(i > 0); // #1 contract_assert(i < 10); // #2 // valid sequence of evaluations: #1 #2 (no repeat) // valid sequence of evaluations: #1 #1 #2 #2 (repeat in sequence) // valid sequence of evaluations: #1 #2 #1 #2 (repeat alternatively) // valid sequence of evaluations: #1 #2 #2 #1 (second occurences can switch order) // invalid sequence of evaluations: #2 #1 (first occurences cannot switch) }

[edit] Notes

The range and flexibility of available choices of evaluation semantics depends on the implementation, and need not allow all four evaluation semantics as possibilities.

Different evaluation semantics chosen for the same contract assertion in different translation units can result in violations of the one-definition rule when a contract assertion has side effects that alter the value produced by a constant expression:

constexpr int f(int i) { contract_assert((++const_cast<int&>(i), true)); return i; }   inline void g() { int a[f(1)]; // size dependent on the evaluation semantic of contract_assert above }

If the value that would result from evaluating the predicate is true, no contract violation occurs and control flow continues normally after the point of evaluation of the contract assertion.

If the evaluation of the predicate exits by means of non-local jumps or terminating the program, no contract violation occurs either.

It is recommended by the C++ standard that the default contract-violation handler should produce diagnostic output that suitably formats the most relevant contents of the argument (rate-limited for potentially repeated violations of observed contract assertions), and then return normally.

Feature-test macro Value Std Feature
__cpp_contracts 202502L (C++26) Contracts

[edit] Keywords

contract_assert,pre,post

[edit] Support status

C++26 feature Paper(s) GCC Clang MSVC Apple Clang EDG eccp Intel C++ Nvidia HPC C++ (ex PGI)* Nvidia nvcc Cray
Contracts (FTM)* P2900R14

[edit] See also