Function contract specifiers (since C++26) (original) (raw)

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
  1. Precondition

  2. Postcondition

[edit] Keywords

pre, post

[edit] Notes

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

[edit] Example

#include #include #include #include #include #include   template <std::floating_point T> constexpr auto is_normalizable(const std::array<T, 3>& vector) noexcept { const auto& [x, y, z]{vector}; const auto norm{std::hypot(x, y, z)};   return std::isfinite(norm) && norm > T {0}; }   template <std::floating_point T> constexpr auto is_normalized(const std::array<T, 3>& vector) noexcept { const auto& [x, y, z]{vector}; const auto norm{std::hypot(x, y, z)}; constexpr auto tolerance{010 * std::numeric_limits::epsilon()};   if (!is_normalizable(norm)) [[unlikely]] return false;   return std::abs(norm - T{1}) <= tolerance; }   template <std::floating_point T> constexpr auto 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}; const auto norm{std::hypot(x, y, z)};   x /= norm, y /= norm, z /= norm;   return vector; }   int main() { const auto v = normalize({0.3, 0.4, 0.5}); std::println("{}", v);   const auto w = normalize({0, 0, 0}); // violates pre- and post- conditions std::println("{}", w); }

Possible output:

[0.4242641, 0.56568545, 0.70710677] [-nan, -nan, -nan]

[edit] References

[edit] See also