Namespaces
Variants

std::experimental:: scope_success

From cppreference.net

ヘッダーで定義 <experimental/scope>
template < class EF >
class scope_success ;
(ライブラリ基盤 TS v3)

クラステンプレート scope_success は、スコープが正常に終了した際に終了関数を呼び出すことを目的とした汎用スコープガードです。

scope_success CopyConstructible CopyAssignable または MoveAssignable ではありません。ただし、 EF が特定の要件を満たす場合、 MoveConstructible になる可能性があり、これにより scope_success を別のオブジェクトでラップすることが可能になります。

A scope_success は、破棄時に終了関数を呼び出すアクティブ状態、または破棄時に何もしない非アクティブ状態のいずれかになります。 scope_success は終了関数から構築された後、アクティブ状態になります。

scope_success は、手動で、または自動的に(ムーブコンストラクタによって)その release() を呼び出すことで非アクティブになります。非アクティブな scope_success は、別の非アクティブな scope_success で初期化することによっても取得できます。 scope_success が一度非アクティブになると、再度アクティブにすることはできません。

A scope_success は事実上、1つの EF と、それがアクティブかどうかを示す bool フラグ、さらにスタックアンワインド中にデストラクタが呼び出されたかどうかを検出するために使用される未捕捉例外のカウンタを保持します。

目次

テンプレートパラメータ

EF - 格納される終了関数の型
型要件
-
EF は以下のいずれかでなければならない:
-
std:: remove_reference_t < EF > の左辺値を引数なしで呼び出すことは、適切な形式でなければならない。

メンバー関数

新しい scope_success を構築する
(公開メンバ関数)
スコープが正常に終了した場合に終了関数を呼び出し、 scope_success がアクティブな場合に scope_success を破棄する
(公開メンバ関数)
operator=
[deleted]
scope_success は代入不可
(公開メンバ関数)
修飾子
scope_success を非アクティブにする
(公開メンバ関数)

推論ガイド

注記

動的ストレージ期間を持つ scope_success の構築は、予期せぬ動作を引き起こす可能性があります。

別のスレッドで作成された scope_success から scope_success を構築すると、破棄時に異なるスレッドで取得された未捕捉例外のカウントが比較される可能性があるため、予期しない動作を引き起こす可能性もあります。

関数内で定義されたローカル変数(例: 参照でキャプチャされたラムダ)が scope_success オブジェクトに格納された EF によって参照され、かつその変数がその関数のreturnオペランドとして使用される場合、 scope_success のデストラクタが実行されexit関数を呼び出す時点では、その変数は既にreturnされている可能性があります。これは予期せぬ動作を引き起こす可能性があります。

#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 << "  例外スロー        " << (did_throw ? "はい" : "いいえ") << "\n";
  std::cout << "  終了ステータス    " << (exit_status ? "完了" : "保留中") << "\n\n";
}
// ランダムに例外をスロー(50%の確率)
void maybe_throw() {
    if (std::rand() >= RAND_MAX / 2)
        throw std::exception{};
}
int main() {
  bool exit_status{false}, did_throw{false};
  // 「スコープ終了時」での手動処理
  try {
    maybe_throw();
    exit_status = true; 
  } catch (...) { did_throw = true; }
  print_exit_status("手動処理", exit_status, did_throw);
  // scope_exitの使用:スコープ終了時(成功時または例外発生時)に実行
  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);
  // scope_failの使用:例外発生時のみ実行
  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);
  // scope_successの使用:例外が発生しなかった場合のみ実行
  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);
}

出力:

手動処理:
  例外スロー        はい
  終了ステータス    保留中
scope_exit:
  例外スロー        いいえ
  終了ステータス    完了
scope_fail:
  例外スロー        はい
  終了ステータス    完了
scope_success:
  例外スロー        はい
  終了ステータス    保留中

関連項目

関数オブジェクトをラップし、スコープ終了時に呼び出す
(クラステンプレート)
関数オブジェクトをラップし、例外によるスコープ終了時に呼び出す
(クラステンプレート)
unique_ptr のためのデフォルト削除子
(クラステンプレート)