標準ライブラリの強化に関する記事では、ライブラリの要件の多くが「コントラクト」として表現されていることを見ました。本稿では C++26 のコントラクトを取り上げ、それを自分のコードにどう適用できるかを探ります。
議論はシンプルな例から始まります。与えられたインデックスで std::vector から値を返す関数です。従来は、インデックスが有効であるという要件を、関数本体内の assert によって強制していました。この方法には欠点があります。要件が実装の中にあるため、宣言だけを読む人には vector とインデックスが見えても、両者の関係は見えません。また、アサーションは NDEBUG によってのみ制御され、定義されているとチェックは完全に取り除かれます。
P2900 で導入された C++26 のコントラクトは、パラメータリストの後に置かれる pre(...) 節によって、要件を関数シグネチャへ移します。この事前条件は、関数に入る時点で成り立つと想定される条件を述べます。同じ要件を宣言に記述することもでき、API を読むすべての人に見えるようになります。コントラクトはいくつかの評価セマンティクスを提供します。チェックを無視する、違反を報告して処理を続ける、プログラムを終了させる、などです。どれが利用可能で、どのように選択されるかは、コンパイラの実装によって決まります。
コントラクトはまた、呼び出し側が提供すべきものと、関数が返すと約束するものを区別します。post で導入される事後条件は、各 return 文の前に手動でチェックを書くことなく、これらの約束を表現します。そのため、実行時チェックが無効化されている場合でも、API を文書化する手段として有用です。
記事は完全な事前条件の例で締めくくられ、事後条件、宣言と定義へのコントラクトの配置、コンパイラオプション、そして開発者を驚かせるかもしれない詳細といったトピックにも触れています。
出典: Hacker News · 要約:HeadlinesBriefing