std::experimental::scope_fail
| ヘッダ <experimental/scope> で定義 |
||
| template< class EF > class scope_fail; |
(ライブラリ基本TS v3) | |
クラステンプレート scope_fail は、スコープが例外によって終了したときに脱出関数を呼び出すことを目的とした、汎用のスコープガードです。
scope_fail は CopyConstructible、CopyAssignable、または MoveAssignable ではありませんが、EF がいくつかの要件を満たす場合には MoveConstructible になり得ます。これにより、scope_fail を別のオブジェクトにラップすることが許可されます。
scope_fail は、アクティブ(破棄時に脱出関数を呼び出す)または非アクティブ(破棄時に何もしない)のいずれかの状態になります。scope_fail は、脱出関数から構築された後、アクティブになります。
scope_fail は、手動または自動(ムーブコンストラクタによる)で release() を呼び出すことで非アクティブにすることができます。非アクティブな scope_fail は、別の非アクティブな scope_fail で初期化することによっても得られます。一度 scope_fail が非アクティブになると、再びアクティブになることはありません。
scope_fail は、実質的に EF と、アクティブかどうかを示す bool フラグを保持します。それに加えて、デストラクタがスタックアンワインド中に呼び出されたかどうかを検出するために使用される、未捕捉の例外のカウンタも保持します。
目次 |
[編集] テンプレートパラメータ
| EF | - | 格納される脱出関数の型 |
| 型要件 | ||
-EF は以下のいずれかでなければなりません。
| ||
| -std::remove_reference_t<EF> の左辺値を引数なしで呼び出すことは、適格でなければなりません。 | ||
[編集] メンバ関数
新しい scope_fail を構築する(公開メンバ関数) | |
scope_fail がアクティブな場合、スコープが例外によって終了するときに脱出関数を呼び出し、その後 scope_fail を破棄する(公開メンバ関数) | |
| operator= [削除] |
scope_fail は代入不可(public member function) |
変更 | |
scope_fail を非アクティブにする(公開メンバ関数) | |
[編集] 推論補助
[編集] ノート
動的記憶域期間を持つ scope_fail を構築すると、予期しない動作につながる可能性があります。
異なるスレッドで作成された別の scope_fail から scope_fail を構築することも、予期しない動作につながる可能性があります。なぜなら、破棄中に異なるスレッドで取得された未捕捉の例外のカウントが比較される可能性があるためです。
[編集] 例
#include <iostream> #include <cstdlib> #include <string_view> #include <experimental/scope> void print_exit_status(std::string_view name, bool exit_status, bool did_throw) { std::cout << name << ":\n"; std::cout << " Throwed exception " << (did_throw ? "yes" : "no") << "\n"; std::cout << " Exit status " << (exit_status ? "finished" : "pending") << "\n\n"; } // Randomly throw an exception (50% chance) void maybe_throw() { if (std::rand() >= RAND_MAX / 2) throw std::exception{}; } int main() { bool exit_status{false}, did_throw{false}; // Manual handling at "end of scope" try { maybe_throw(); exit_status = true; } catch (...) { did_throw = true; } print_exit_status("Manual handling", exit_status, did_throw); // Using scope_exit: runs on scope exit (success or exception) exit_status = did_throw = false; try { auto guard = std::experimental::scope_exit{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_exit", exit_status, did_throw); // Using scope_fail: runs only if an exception occurs exit_status = did_throw = false; try { auto guard = std::experimental::scope_fail{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_fail", exit_status, did_throw); // Using scope_success: runs only if no exception occurs exit_status = did_throw = false; try { auto guard = std::experimental::scope_success{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_success", exit_status, did_throw); }
出力
Manual handling: Throwed exception yes Exit status pending scope_exit: Throwed exception no Exit status finished scope_fail: Throwed exception yes Exit status finished scope_success: Throwed exception yes Exit status pending
[編集] 関連項目
| 関数オブジェクトをラップし、スコープを抜ける際にそれを呼び出す (クラステンプレート) | |
| 関数オブジェクトをラップし、正常にスコープを抜ける際にそれを呼び出す (クラステンプレート) | |
| (C++11) |
unique_ptr のためのデフォルトデリータ (クラステンプレート) |