188
188
189
189
< p class ="text-right "> < small >
190
190
最終更新日時(UTC):
191
- < span itemprop ="datePublished " content ="2025-04-20T14:00:30 ">
192
- 2025年04月20日 14時00分30秒
191
+ < span itemprop ="datePublished " content ="2025-04-23T03:06:32 ">
192
+ 2025年04月23日 03時06分32秒
193
193
</ span >
194
194
< br />
195
195
< span itemprop ="author " itemscope itemtype ="http://schema.org/Person ">
@@ -222,6 +222,22 @@ <h2>概要</h2>
222
222
< p > これにより、< a class ="cpprefjp-defined-word " data-desc ="関数等の意味論を構成する要素の1つ。Preconditions。関数呼び出し時に満たされていると関数が想定する条件。満たさなければ未定義の動作。契約属性の`[[expects]]`に相当 "> 事前条件</ a > (preconditions)、< a class ="cpprefjp-defined-word " data-desc ="関数等の意味論を構成する要素の1つ。Postconditions。関数を実行後に満たされている条件。契約属性の`[[ensures]]`に相当 "> 事後条件</ a > (postconditions)、及びアサーション(assertions)をコード内で明示的に記述できるようになる。</ p >
223
223
< p > この機能は、関数のインターフェースに対する期待値を明確にする役割があり、バグの早期発見、コードの可読性向上に寄与することが期待されている。</ p >
224
224
< h2 > 仕様</ h2 >
225
+ < h3 > キーワード</ h3 >
226
+ < p > < code > pre</ code > 、< code > post</ code > 、< code > assert</ code > は文脈依存キーワードである。これらは< code > override</ code > や< code > final</ code > と同様に、特定の文脈でのみ特別な意味を持つ。</ p >
227
+ < ul >
228
+ < li > 変数名や関数名として使用可能
229
+ < br />
230
+ < div class ="codehilite "> < pre > < span > </ span > < code > < span class ="kt "> int</ span > < span class ="n "> pre</ span > < span class ="o "> =</ span > < span class ="mi "> 42</ span > < span class ="p "> ;</ span > < span class ="c1 "> // OK: 変数名として使用</ span >
231
+ < span class ="kt "> void</ span > < span class ="nf "> post</ span > < span class ="p "> ()</ span > < span class ="p "> {}</ span > < span class ="c1 "> // OK: 関数名として使用</ span >
232
+ </ code > </ pre > </ div >
233
+ </ li >
234
+ < li > 契約指定の文脈でのみ特別な意味を持つ
235
+ < br />
236
+ < div class ="codehilite "> < pre > < span > </ span > < code > < span class ="kt "> void</ span > < span class ="nf "> f</ span > < span class ="p "> ()</ span >
237
+ < span class ="n "> pre</ span > < span class ="p "> (</ span > < span class ="nb "> true</ span > < span class ="p "> );</ span > < span class ="c1 "> // ここでは契約指定として機能</ span >
238
+ </ code > </ pre > </ div >
239
+ </ li >
240
+ </ ul >
225
241
< h3 > 契約の種類</ h3 >
226
242
< p > 契約には以下の3種類が定められている。</ p >
227
243
< ul >
@@ -239,6 +255,23 @@ <h4><a class="cpprefjp-defined-word" data-desc="関数等の意味論を構成
239
255
</ code > </ pre > </ div >
240
256
241
257
ここでは、< code > denominator</ code > が0でないことを< a class ="cpprefjp-defined-word " data-desc ="関数等の意味論を構成する要素の1つ。Preconditions。関数呼び出し時に満たされていると関数が想定する条件。満たさなければ未定義の動作。契約属性の`[[expects]]`に相当 "> 事前条件</ a > として指定している。</ p >
258
+ < p > < a class ="cpprefjp-defined-word " data-desc ="関数等の意味論を構成する要素の1つ。Preconditions。関数呼び出し時に満たされていると関数が想定する条件。満たさなければ未定義の動作。契約属性の`[[expects]]`に相当 "> 事前条件</ a > では、必ずしも関数のパラメータを使用する必要はない。グローバル状態やクラスのメンバ変数など、呼び出し時点で有効な任意の式を使用できる。</ p >
259
+ < p > < div class ="codehilite "> < pre > < span > </ span > < code > < span class ="k "> class</ span > < span class ="nc "> Resource</ span > < span class ="p "> {</ span >
260
+ < span class ="k "> private</ span > < span class ="o "> :</ span >
261
+ < span class ="kt "> bool</ span > < span class ="n "> is_available</ span > < span class ="o "> =</ span > < span class ="nb "> false</ span > < span class ="p "> ;</ span >
262
+ < span class ="k "> public</ span > < span class ="o "> :</ span >
263
+ < span class ="kt "> void</ span > < span class ="n "> use</ span > < span class ="p "> ()</ span >
264
+ < span class ="n "> pre</ span > < span class ="p "> (</ span > < span class ="n "> is_available</ span > < span class ="p "> )</ span > < span class ="c1 "> // 引数を使用していない事前条件</ span >
265
+ < span class ="p "> {</ span >
266
+ < span class ="c1 "> // リソースを使用</ span >
267
+ < span class ="p "> }</ span >
268
+
269
+ < span class ="kt "> void</ span > < span class ="n "> activate</ span > < span class ="p "> ()</ span > < span class ="p "> {</ span >
270
+ < span class ="n "> is_available</ span > < span class ="o "> =</ span > < span class ="nb "> true</ span > < span class ="p "> ;</ span >
271
+ < span class ="p "> }</ span >
272
+ < span class ="p "> };</ span >
273
+ </ code > </ pre > </ div >
274
+ </ p >
242
275
< h4 > < a class ="cpprefjp-defined-word " data-desc ="関数等の意味論を構成する要素の1つ。Postconditions。関数を実行後に満たされている条件。契約属性の`[[ensures]]`に相当 "> 事後条件</ a > (post)</ h4 >
243
276
< p > 関数の実行後に満たされているべき条件を指定する。</ p >
244
277
< p > < div class ="codehilite "> < pre > < span > </ span > < code > < span class ="kt "> int</ span > < span class ="nf "> increment</ span > < span class ="p "> (</ span > < span class ="kt "> int</ span > < span class ="n "> x</ span > < span class ="p "> )</ span >
@@ -250,6 +283,23 @@ <h4><a class="cpprefjp-defined-word" data-desc="関数等の意味論を構成
250
283
251
284
ここでは、< code > increment</ code > 関数の< a class ="cpprefjp-defined-word " data-desc ="関数呼び出し式の評価結果となるオブジェクト・値 "> 戻り値</ a > が< code > x + 1</ code > であることを< a class ="cpprefjp-defined-word " data-desc ="関数等の意味論を構成する要素の1つ。Postconditions。関数を実行後に満たされている条件。契約属性の`[[ensures]]`に相当 "> 事後条件</ a > として指定している。</ p >
252
285
< p > < code > post</ code > では、返り値を< code > r</ code > としてバインドし、条件式内で利用している。ここには、任意の変数名が使用できる。変数は定数(< code > const</ code > )な左辺値参照である。</ p >
286
+ < p > < a class ="cpprefjp-defined-word " data-desc ="関数等の意味論を構成する要素の1つ。Postconditions。関数を実行後に満たされている条件。契約属性の`[[ensures]]`に相当 "> 事後条件</ a > の結果名導入子(result-name-introducer)は省略可能である。特に、< code > void</ code > を返す関数では、< a class ="cpprefjp-defined-word " data-desc ="関数呼び出し式の評価結果となるオブジェクト・値 "> 戻り値</ a > を参照する必要がない場合に省略できる。</ p >
287
+ < p > < div class ="codehilite "> < pre > < span > </ span > < code > < span class ="k "> class</ span > < span class ="nc "> Container</ span > < span class ="p "> {</ span >
288
+ < span class ="c1 "> // ...</ span >
289
+ < span class ="k "> public</ span > < span class ="o "> :</ span >
290
+ < span class ="kt "> void</ span > < span class ="n "> clear</ span > < span class ="p "> ()</ span >
291
+ < span class ="n "> post</ span > < span class ="p "> (</ span > < span class ="n "> empty</ span > < span class ="p "> ())</ span > < span class ="c1 "> // 結果名導入子を省略した事後条件</ span >
292
+ < span class ="p "> {</ span >
293
+ < span class ="c1 "> // コンテナの内容をクリア</ span >
294
+ < span class ="p "> }</ span >
295
+
296
+ < span class ="kt "> bool</ span > < span class ="n "> empty</ span > < span class ="p "> ()</ span > < span class ="k "> const</ span > < span class ="p "> {</ span >
297
+ < span class ="c1 "> // コンテナが空かどうかを返す</ span >
298
+ < span class ="k "> return</ span > < span class ="nb "> true</ span > < span class ="p "> ;</ span >
299
+ < span class ="p "> }</ span >
300
+ < span class ="p "> };</ span >
301
+ </ code > </ pre > </ div >
302
+ </ p >
253
303
< h4 > アサーション(assert)</ h4 >
254
304
< p > 関数の実行中に満たされているべき条件を指定する。</ p >
255
305
< p > < div class ="codehilite "> < pre > < span > </ span > < code > < span class ="kt "> void</ span > < span class ="nf "> return_negative</ span > < span class ="p "> (</ span > < span class ="kt "> int</ span > < span class ="n "> value</ span > < span class ="p "> )</ span >
@@ -302,7 +352,7 @@ <h3>使用上の注意</h3>
302
352
< ul >
303
353
< li > 契約式内において副作用を要する式を記述した場合(グローバル変数の変更、< code > volatile</ code > 変数への参照、< code > constexpr</ code > でない関数の呼び出しなど)</ li >
304
354
< li > 契約式内で< a class ="cpprefjp-defined-word " data-desc ="問題が発生したときに、現在実行位置を過去に通過・記録した位置に戻し、文脈情報を添えて紐づけられた処理(例外ハンドラー)を呼び出す仕組み。またはその事態 "> 例外</ a > を送出すると、std::terminate()が呼び出され、プログラムが終了する。</ li >
305
- < li > 通常の関数やメンバ関数には契約を適用できるが、特殊な関数(例えば< code > default</ code > によって定義されたコピーコンストラクタやデストラクタ)には適用できない。適用すると、プログラムは不正 (ill-formed)となる。</ li >
355
+ < li > 通常の関数やメンバ関数には契約を適用できるが、特殊な関数(例えば< code > default</ code > によって定義されたコピーコンストラクタやデストラクタ)には適用できない。適用すると、プログラムは < a class =" cpprefjp-defined-word " data-desc =" プログラムが適格でないこと。コンパイルエラーなどになる " href =" ../../implementation-compliance.html#dfn-ill-formed " > 不適格 </ a > (ill-formed)となる。</ li >
306
356
</ ul >
307
357
< h2 > < a href ="#relative-page " id ="relative-page "> 関連項目</ a > </ h2 >
308
358
< ul >
0 commit comments