Namespaces
Variants

Function contract specifiers (since C++26)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
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
Special member functions
Templates
Miscellaneous

Спецификаторы контракта функции (предусловия, обозначаемые с помощью pre и постусловия, обозначаемые с помощью post ) — это спецификаторы, которые могут применяться к декларатору функции или лямбда-выражения для введения утверждения контракта функции соответствующего типа в связанную функцию.

Они гарантируют, что указанное условие выполняется во время исполнения, вызывая нарушение (например, завершение программы) в отладочных сборках, если условие вычисляется в false или вычисление завершается через исключение, и могут игнорироваться в релизных сборках для повышения производительности.

Содержание

Предусловие

Условие ( pre ) — это предикат, который вызывающая сторона должна гарантировать выполнение до вызова функции или лямбды, проверяемый в отладочных сборках для валидации входных данных или состояния.

Постусловие

Постусловие ( post ) — это предикат, который вызываемый объект должен гарантировать выполнение после завершения функции или лямбды, проверяемый в отладочных сборках для подтверждения вывода или состояния.

Синтаксис

pre attr  (необязательно) ( expr ) (1)
post attr  (необязательно) ( result-name  (необязательно) predicate ) (2)
attr - любое количество атрибутов
result-name - identifier :
identifier - имя привязки результата ассоциированной функции
predicate - логическое выражение, которое должно вычисляться в true
1) Предусловие
2) Постусловие

Ключевые слова

pre , post

Примечания

Макрос проверки функциональности Значение Стандарт Функциональность
__cpp_contracts 202502L (C++26) Контракты

Пример

  • Преусловие функции normalize требует от вызывающей стороны передачи нормализуемого вектора.
  • Постусловие гарантирует, что функция normalize возвращает нормализованный вектор.
#include <array>
#include <cmath>
#include <concepts>
#include <contracts>
#include <limits>
#include <print>
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<T>::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<float>({0.3, 0.4, 0.5});
    std::println("{}", v);
    const auto w = normalize<float>({0, 0, 0}); // нарушает пред- и пост- условия
    std::println("{}", w);
}

Возможный вывод:

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

Ссылки

  • Стандарт C++26 (ISO/IEC 14882:2026):
  • 9.(3+ c  ) Спецификаторы контрактов функций [dcl.contract]

Смотрите также

Утверждения контрактов (C++26) определяет свойства, которые должны выполняться в определенных точках во время выполнения
contract_assert statement (C++26) проверяет внутреннее условие во время выполнения