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 )は、 callee が関数またはラムダの完了 に保持されることを保証しなければならない述語であり、出力または状態を確認するためにデバッグビルドで検証されます。

構文

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 (C++26) 実行中の内部条件を検証する