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 声明)是可应用于函数或lambda表达式声明符的说明符,用于向对应函数引入相应类型的函数契约断言。

它们确保在程序执行期间指定条件保持成立,若条件评估结果为 false 或评估过程因异常退出,则在调试版本中触发违规行为(例如终止程序),为提升性能在发布版本中可忽略这些检查。

目录

前置条件

前置条件( pre )是一个谓词, 调用方 必须确保在调用函数或lambda表达式 之前 该条件成立,在调试版本中会进行检查以验证输入或状态。

后置条件

后置条件( post )是一个谓词,要求 被调用方 必须确保在函数或lambda完成 之后 成立,在调试版本中会进行验证以确认输出或状态。

语法

pre 属性  (可选) ( 表达式 ) (1)
post 属性  (可选) ( 结果名称  (可选) 谓词 ) (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 语句 (C++26) 在程序执行期间验证内部条件