Function contract specifiers (since C++26)
Function contract specifiers (preconditions spelled with pre and postconditions spelled with post) are specifiers that may be applied to the declarator of a function or of a lambda expression to introduce a function contract assertion of the respective kind to the corresponding function.
They ensure the specified condition holds during execution, triggering a violation (e.g. termination) in debug builds if the condition evaluates to false or the evaluation exits via an exception, and can be ignored in release builds for performance.
Contents |
[edit]Precondition
A precondition (pre) is a predicate that the caller must ensure holds before invoking a function or lambda, checked in debug builds to validate inputs or state.
[edit]Postcondition
A postcondition (post) is a predicate that the callee must ensure holds after a function or lambda completes, verified in debug builds to confirm output or state.
[edit]Syntax
pre attr (optional)( expr) | (1) | ||||||||
post attr (optional)( result-name (optional)predicate) | (2) | ||||||||
attr | - | any number of attributes |
result-name | - | identifier: |
identifier | - | name of a result binding of the associated function |
predicate | - | boolean expression that should evaluate to true |
[edit]Keywords
[edit]Notes
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_contracts | 202502L | (C++26) | Contracts |
[edit]Example
- The precondition of function
normalize
requires caller to pass normalizable vector. - The postcondition ensures that the function
normalize
returns a normalized vector.
#include <array>#include <cmath>#include <concepts>#include <contracts>#include <limits>#include <print> template<std::floating_point T>constexprauto is_normalizable(conststd::array<T, 3>& vector)noexcept{constauto&[x, y, z]{vector};constauto norm{std::hypot(x, y, z)}; returnstd::isfinite(norm)&& norm > T {0};} template<std::floating_point T>constexprauto is_normalized(conststd::array<T, 3>& vector)noexcept{constauto&[x, y, z]{vector};constauto norm{std::hypot(x, y, z)};constexprauto tolerance{010*std::numeric_limits<T>::epsilon()}; if(!is_normalizable(norm))[[unlikely]]returnfalse; return std::abs(norm - T{1})<= tolerance;} template<std::floating_point T>constexprauto normalize(std::array<T, 3> vector)noexcept->std::array<T, 3> pre(is_normalizable(vector)) post(vector: is_normalized(vector)){auto&[x, y, z]{vector};constauto norm{std::hypot(x, y, z)}; x /= norm, y /= norm, z /= norm; return vector;} int main(){constauto v = normalize<float>({0.3, 0.4, 0.5});std::println("{}", v); constauto w = normalize<float>({0, 0, 0});// violates pre- and post- conditionsstd::println("{}", w);}
Possible output:
[0.4242641, 0.56568545, 0.70710677] [-nan, -nan, -nan]
[edit]References
- C++26 standard (ISO/IEC 14882:2026):
- 9.(3+c ) Function contract specifiers [dcl.contract]
[edit]See also
Contract assertions(C++26) | specifies properties that must hold at certain points during execution |
contract_assert statement(C++26) | verifies an internal condition during execution |