Namespaces
Variants
Views
Actions

Contract assertions (since C++26)

From cppreference.com
< cpp‎ | language
 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 
 

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:

  • The value that would result from evaluating the predicate is false.
  • The evaluation of the predicate exits via an exception.
  • The evaluation of the predicate is performed in a context that is manifestly constant-evaluated and the predicate is not a core constant expression.

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 the evaluation semantic is “observe”, a diagnostic is produced.
  • If the evaluation semantic is a terminating semantic, the program is ill-formed.

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

  • If the evaluation semantic is “quick-enforce”, the program is contract-terminated.
  • If the evaluation semantic is “enforce” or “observe”, the contract-violation handler is invoked with an lvalue referring to an object obj of type const std::contracts::contract_violation containing information about the contract violation.
    • Storage for obj is allocated in an unspecified manner, but no global allocation function will be invoked.
    • The lifetime of obj persists for the duration of the invocation of the contract-violation handler.

[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:

  • If the evaluation semantic is “observe”, control flow continues normally after the point of evaluation of the contract assertion.
  • If the evaluation semantic is “enforce”, the program is contract-terminated.

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:

  • If the evaluation semantic is “observe”, the implicit handler is no longer considered active.
  • If the evaluation semantic is “enforce”, the implicit handler remains active when contract termination occurs.

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:
  • All elements of R are in S.
  • Each element of R may be repeated an implementation-defined number of times within S.
  • If a contract assertion A precedes another contract assertion B in R, then the first occurrence of A precedes the first occurrence of B in S.
2) 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

contract_assert statement (C++26) verifies an internal condition during execution[edit]
function contract specifiers (C++26) specifies preconditions (pre) and postconditions (post)[edit]