Skip to content

Commit 9d5321d

Browse files
committed
lang/cpp26.md,lang/cpp26/contracts.md,implementation-status.md: Created article
This commit creates lang/cpp26/contracts.md. This is for issue #1419
1 parent 28659ac commit 9d5321d

File tree

3 files changed

+113
-2
lines changed

3 files changed

+113
-2
lines changed

implementation-status.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@
319319
| P1061R10: [構造化束縛でパックを導入できるようにする](/lang/cpp26/structured_bindings_can_introduce_a_pack.md) | タプルを分解する際に複数の変数をパックとして宣言できるようにする。`auto [a, ...xs] = f();` | | | | |
320320
| P3176R0: [先行するカンマのない省略記号を非推奨化](/lang/cpp26/the_oxford_variadic_comma.md.nolink) | `void f(int, ...);`はOK。`void f(int...);`は非推奨 | 15 | 20 | | |
321321
| P3074R7: [共用体をトリビアルに未初期化できるようにする](/lang/cpp26/trivial_unions.md.nolink) | `constexpr`での`union U { T storage[N]; };`を許可し、未初期化にできるようにする | | | | |
322-
| P2900R14: [契約プログラミングをサポートする](/lang/cpp26/contracts.md.nolink) | 関数の事前条件、事後条件、不変条件を記述できるようにする | | | | |
322+
| P2900R14: [契約プログラミングをサポートする](/lang/cpp26/contracts.md) | 関数の事前条件、事後条件、不変条件を記述できるようにする | | | | |
323323
| P2841R7: [コンセプトと変数テンプレートにテンプレートテンプレートパラメータのサポートを追加](/lang/cpp26/concept_and_variable-template_template-parameters.md.nolink) | テンプレート引数をあとで指定するテンプレートテンプレートパラメータを、コンセプトと変数テンプレートでも使用できるようにする | | | | |
324324
| P2786R13: [トリビアルな再配置](/lang/cpp26/trivial_relocatability.md.nolink) | ムーブ構築と破棄のためにビット単位のコピーとデストラクタ評価が必要になる型のオブジェクトを再配置するメカニズムを導入する | | | | |
325325
| P1967R14: [ファイルを読み込む`#embed`命令を追加](/lang/cpp26/embed.md) | バイナリファイルをインクルードするメカニズム。`#include`とちがって読み出しサイズなどの柔軟な指定ができる | 15 | | | |

lang/cpp26.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
4343
| 言語機能 | 説明 |
4444
|----------|------|
4545
| [関数宣言を削除する理由を指定できるようにする](/lang/cpp26/delete_reason.md) | `f() = delete("reason");` |
46-
| [契約プログラミングをサポートする](/lang/cpp26/contracts.md.nolink) | 関数の事前条件、事後条件、不変条件を記述できるようにする |
46+
| [契約プログラミングをサポートする](/lang/cpp26/contracts.md) | 関数の事前条件、事後条件、不変条件を記述できるようにする |
4747

4848

4949
### クラス

lang/cpp26/contracts.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# 契約プログラミング [P2900R14]
2+
* cpp26[meta cpp]
3+
4+
<!-- start lang caution -->
5+
6+
このページはC++26に採用される見込みの言語機能の変更を解説しています。
7+
8+
のちのC++規格でさらに変更される場合があるため[関連項目](#relative-page)を参照してください。
9+
10+
<!-- last lang caution -->
11+
12+
## 概要
13+
C++26では、関数の正確な動作を明示的に指定でき、プログラムの正当性を高めるために「契約プログラミング」機能が導入される。
14+
15+
これにより、事前条件(preconditions)、事後条件(postconditions)、及びアサーション(assertions)をコード内で明示的に記述できるようになる。
16+
17+
この機能は、関数のインターフェースに対する期待値を明確にする役割があり、バグの早期発見、コードの可読性向上に寄与することが期待されている。
18+
19+
## 仕様
20+
### 契約の種類
21+
契約には以下の3種類が定められている。
22+
23+
- 事前条件(preconditions)
24+
- 事後条件(postconditions)
25+
- アサーション(assertions)
26+
27+
#### 事前条件(pre)
28+
関数が呼び出される前に満たされているべき条件を指定する。
29+
```cpp
30+
int safe_division(int numerator, int denominator)
31+
pre(denominator != 0)
32+
{
33+
return numerator / denominator;
34+
}
35+
```
36+
ここでは、`denominator`が0でないことを事前条件として指定している。
37+
38+
#### 事後条件(post)
39+
関数の実行後に満たされているべき条件を指定する。
40+
```cpp
41+
int increment(int x)
42+
post(r: r == x + 1)
43+
{
44+
return x + 1;
45+
}
46+
```
47+
ここでは、`increment`関数の戻り値が`x + 1`であることを事後条件として指定している。
48+
49+
`post`では、返り値を`r`としてバインドし、条件式内で利用している。ここには、任意の変数名が使用できる。変数は定数(`const`)な左辺値参照である。
50+
51+
#### アサーション(assert)
52+
関数の実行中に満たされているべき条件を指定する。
53+
```cpp
54+
void return_negative(int value)
55+
{
56+
contract_assert(value >= 0);
57+
return -value;
58+
}
59+
```
60+
ここでは、`return_negative`関数のが引数として受け取っている`value`が0以上であることをアサーションとして指定している。
61+
62+
`contract_assert`は、関数の本体内で使用される。
63+
64+
また、これらの全ては、`[[ likely ]]`や`[[ unlikely ]]`、 `[[ maybe_unused ]]`属性を使用することができる。
65+
```cpp
66+
void return_negative(int value)
67+
pre [[likely]] (value >= 0)
68+
post (r [[maybe_unused]] : r <= 0)
69+
{
70+
return -value;
71+
}
72+
```
73+
### 評価の順番
74+
契約式の評価順序に注意が必要である。
75+
76+
事前条件は関数の引数が初期化された後に評価され、事後条件は関数の戻り値が初期化された後、ローカル変数の破棄前に評価される。この順序により、契約式は必要な変数や状態にアクセスできるようになっている。
77+
78+
### 契約の評価モード
79+
契約の評価には、次の4つのモードが存在する。
80+
81+
- ignore: 契約のチェックを無視(ignore)する。
82+
83+
- observe: 契約違反時にハンドラを呼び出し、プログラムの実行を続行します。
84+
85+
- enforce: 契約違反時にハンドラを呼び出し、プログラムを終了します。
86+
87+
- quick_enforce: 契約違反時にハンドラを呼び出さず、即座にプログラムを終了します。
88+
89+
評価モードは、コンパイル時、もしくは実行時に指定できる。
90+
91+
GCCでは、
92+
```bash
93+
g++ -std=c++26 -fcontracts -fcontract-semantic=observe main.cpp
94+
```
95+
のように指定できる。
96+
97+
### 契約違反ハンドラ
98+
契約違反が発生した場合、`std::contracts::contract_violation`型の情報(&lt;contracts&gt;ヘッダー)がハンドラに渡されます。​この情報には、違反の種類、発生場所、違反した条件式などが含まれます。
99+
100+
### 使用上の注意
101+
以下の操作は、気をつけなければならない。
102+
- 契約式内において副作用を要する式を記述した場合(グローバル変数の変更、`volatile`変数への参照、`constexpr`でない関数の呼び出しなど)
103+
- 契約式内で例外を送出すると、std::terminate()が呼び出され、プログラムが終了する。
104+
- 通常の関数やメンバ関数には契約を適用できるが、特殊な関数(例えば`default`によって定義されたコピーコンストラクタやデストラクタ)には適用できない。適用すると、プログラムは不正(ill-formed)となる。
105+
106+
## <a id="relative-page" href="#relative-page">関連項目</a>
107+
- [C++ 将来 契約に基づくプログラミング](lang/future/contract-based_programming.md)
108+
109+
110+
## 参照
111+
- [P2900R14 `Contracts for C++`](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2900r14.pdf)

0 commit comments

Comments
 (0)