函数契约说明符 (C++26 起)
来自cppreference.com
函数契约说明符(前条件写为 pre,后条件写为 post)是可应用于函数或 lambda 表达式的声明符的说明符,以向对应函数引入相应种类的函数契约断言。
它们确保指定的条件成立在执行时,在调试构建中当条件求值为 false,或者求值由于异常退出时触发违例(如终止程序),也可在发布构建中为性能而将之忽略。
前条件
前条件 (pre) 是调用方必须确保于调用函数或 lambda 之前 成立的谓词,调试构建中检查它以验证输入或状态。
后条件
后条件 (post) 是被调用方必须确保于函数或 lambda 执行结束之后 成立的谓词,调试构建中验证它以确认输出或状态。
语法
pre 属性 (可选) ( 表达式 )
|
(1) | ||||||||
post 属性 (可选) ( 结果名 (可选) 谓词 )
|
(2) | ||||||||
| 属性 | - | 任意数量的属性 |
| 结果名 | - | 标识符 :
|
| 标识符 | - | 与关联函数的结果绑定的名字 |
| 谓词 | - | 应当求值为 true 的布尔表达式
|
1) 前条件
2) 后条件
关键词
注解
| 功能特性测试宏 | 值 | 标准 | 功能特性 |
|---|---|---|---|
__cpp_contracts |
202502L |
(C++26) | 契约 |
示例
- 函数
normalize的前条件要求调用方传递可正规化的向量。 - 后条件则保证函数
normalize返回正规化后的vector。
运行此代码
#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 ) Function contract specifiers [dcl.contract]
