名前空間
変種
操作

関数契約指定子 (C++26以降)

From cppreference.com
< cpp‎ | language‎ | functions
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

関数契約指定子(pre で記述される事前条件と post で記述される事後条件)は、関数またはラムダ式の宣言子に適用して、それぞれの種類の関数契約アサーションを導入できる指定子です。

これらは、実行中に指定された条件が成り立つことを保証し、デバッグビルドで条件が false と評価された場合や、例外を介して評価が終了した場合に違反(例: 終了)をトリガーし、リリースビルドではパフォーマンスのために無視できます。

目次

[編集] 事前条件

事前条件(pre)は、関数またはラムダを呼び出す *前に* 呼び出し元が満たす必要がある述語であり、デバッグビルドで入力を検証したり状態を確認したりするためにチェックされます。

[編集] 事後条件

事後条件(post)は、関数またはラムダが完了した *後に* 被呼び出し元が満たす必要がある述語であり、デバッグビルドで出力を確認したり状態を検証したりするために使われます。

[編集] 構文

pre attr (optional) ( expr ) (1)
post attr (optional) ( result-name (optional) predicate ) (2)
attr - 任意の数の属性
result-name - identifier :
identifier - 関連する関数の結果バインディングの名前
predicate - true と評価されるべきブール式
1) 事前条件
2) 事後条件

[編集] キーワード

prepost

[編集] 注釈

機能テストマクロ 規格 機能
__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) 実行中に内部条件を検証する[編集]
English 日本語 中文(简体) 中文(繁體)