8例外安全性のレベルと、noexcept がムーブ操作、コンテナ、およびコード生成に与える影響について説明してください。
例外安全性(exception safety)の各レベルは、ある操作が例外を送出した際にどのような状態が保たれるかを定義します。基本保証(basic guarantee)は、不変条件が維持されリソースリークが発生しないことを意味しますが、状態が変更されている可能性はあります。強い保証(strong guarantee)はコミットまたはロールバックのセマンティクスを意味し、失敗時にも観測可能な状態は変更されません。非送出保証(nothrow guarantee)は、操作が例外を送出しないことを意味します。代表的な手法には、RAII(Resource Acquisition Is Initialization)、一時オブジェクトでの作業、コピー&スワップ(copy-and-swap)、そして例外を送出しうる処理が成功した後にのみコミットが行われるような状態変更順序の制御などがあります。`noexcept` は契約であり、`noexcept` 関数が例外を送出した場合は `std::terminate` が呼び出されます。また、ジェネリックコードやコンテナにも影響を与えます。例えば再割り当て時、`std::vector` はムーブコンストラクタが `noexcept` であれば要素をムーブできますが、そうでなければ例外保証を維持するために、多くの場合 `std::move_if_noexcept` を介してコピーを行います。さらに `noexcept` は、必要な例外伝播パスを削減することでコード生成や最適化に寄与することもありますが、それは指定した約束が正しい場合に限られます。
std::vector<T> v;
// During reallocation, an implementation may effectively do:
T* dest = allocate(new_cap);
for (T& x : old_storage) {
construct(dest++, std::move_if_noexcept(x));
}
AI コーチを使ってこの質問に答えてみる
9失敗する可能性のある処理において、例外の代替手段としての `std::expected` や同等の outcome 型について説明してください。
`std::expected<T, E>` は、成功時の値 `T` または明示的なエラー `E` のいずれかを表し、例外の伝播に依存する代わりに失敗を関数の戻り値の型の一部にします。これは、パース処理、バリデーション、ネットワーク呼び出し、ストレージ検索、リトライ可能なバックエンド処理など、エラーが想定され呼び出し側で局所的に処理すべき失敗しやすい操作に適しています。エラー型には、エラーコード、カテゴリ、リトライ可否、メッセージ、HTTP/RPCマッピングなどの構造化された情報を持たせるべきです。expected/outcome 型はエラーを検査して伝播させることで合成可能であり、C++23 スタイルの API では `and_then`、`transform`、`or_else` などのモナド操作を利用して、深くネストした条件分岐を作らずに処理ステップを連結できます。例外と比較すると、制御フローと API の契約が明示的になり、例外を使用しない環境や ABI 境界をまたぐ場合でもうまく機能します。プロジェクトの方針によっては、稀にしか発生しない非局所的な障害や、真に例外的な失敗に対しては依然として例外が適切な場合もあります。
enum class Errc { BadRequest, NotFound, Timeout, DbUnavailable };
struct Error {
Errc code;
bool retryable;
std::string message;
};
std::expected<User, Error> load_user(UserId id);
HttpResponse handle(UserId id) {
auto user = load_user(id);
if (!user) {
switch (user.error().code) {
case Errc::BadRequest: return {400, user.error().message};
case Errc::NotFound: return {404, "not found"};
case Errc::Timeout: return {503, "try again"};
case Errc::DbUnavailable: return {503, "service unavailable"};
}
}
return {200, serialize(*user)};
}
AI コーチを使ってこの質問に答えてみる