Спецификаторы контрактов функции (начиная с C++26)
Спецификаторы контрактов функции (предусловия, записываемые с помощью pre, и постусловия, записываемые с помощью post) могут применяться к объявлению функции или лямбда-выражения для добавления к соответствующей функции контрактного утверждения соответствующего вида.
Они гарантируют выполнение заданного условия во время исполнения: в отладочных сборках при вычислении условия в false или при завершении вычисления исключением возникает нарушение контракта (например, программа завершается), а в релизных сборках для повышения производительности проверку можно пропустить.
Предусловие
Предусловие (pre) — это предикат, выполнение которого вызывающий код должен обеспечить до вызова функции или лямбда-выражения; в отладочных сборках оно проверяется для валидации входных данных или состояния.
Постусловие
Постусловие (post) — это предикат, выполнение которого вызываемая функция должна обеспечить после завершения функции или лямбда-выражения; в отладочных сборках оно проверяется для подтверждения корректности выходных данных или состояния.
Синтаксис
pre attr (необязательно) ( expr ) | (1) | |
post attr (необязательно) ( result-name (необязательно) predicate ) | (2) |
| attr | - | любое количество атрибутов |
| result-name | - |
identifier : |
| identifier | - | имя привязки результата связанной функции |
| predicate | - | логическое выражение, результатом вычисления которого должно быть true |
Ключевые слова
Примечания
| Макрос проверки поддержки функции | Значение | Стандарт | Функция |
|---|---|---|---|
__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