Spec-Zone.ru › C++

Спецификаторы контрактов функции (начиная с C++26)

Спецификаторы контрактов функции (предусловия, записываемые с помощью 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}); // violates pre- and post- conditions
    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 (C++26) проверяет внутреннее условие во время исполнения

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/functions/function_contract_specifiers

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API