Namespaces
Variants

std::experimental:: scope_exit

From cppreference.net

Определено в заголовке <experimental/scope>
template < class EF >
class scope_exit ;
(Technical Specification v3 библиотеки фундаментальных компонентов)

Класс-шаблон scope_exit является универсальной защитой области видимости, предназначенной для выхода своей функции выхода при выходе из области видимости.

scope_exit не является CopyConstructible , CopyAssignable или MoveAssignable , однако может быть MoveConstructible , если EF удовлетворяет определённым требованиям, что позволяет оборачивать scope_exit в другой объект.

Объект scope_exit может быть активным, т.е. вызывать свою завершающую функцию при разрушении, или неактивным, т.е. не делать ничего при разрушении. scope_exit активен после создания из завершающей функции.

Объект scope_exit может стать неактивным при вызове метода release() либо вручную, либо автоматически (через конструктор перемещения). Неактивный scope_exit также может быть получен при инициализации другим неактивным объектом scope_exit . После того как scope_exit становится неактивным, он не может снова стать активным.

Объект scope_exit фактически содержит EF и флаг bool , указывающий, активен ли он.

Содержание

Параметры шаблона

EF - тип хранимой функции выхода
Требования к типу
-
EF должен быть либо:
-
Вызов lvalue типа std:: remove_reference_t < EF > без аргументов должен быть корректным.

Функции-члены

создает новый scope_exit
(публичная функция-член)
вызывает функцию выхода при выходе из области видимости, если scope_exit активен, затем уничтожает scope_exit
(публичная функция-член)
operator=
[deleted]
scope_exit не может быть присвоен
(публичная функция-член)
Модификаторы
делает scope_exit неактивным
(публичная функция-член)

Руководства по выводу

Примечания

Создание объекта scope_exit с динамической продолжительностью хранения может привести к непредсказуемому поведению.

Если EF , хранимый в объекте scope_exit , ссылается на локальную переменную функции, в которой он определен, например, как лямбда-выражение, захватывающее переменную по ссылке, и эта переменная используется в качестве операнда возврата в этой функции, эта переменная может быть уже возвращена, когда деструктор scope_exit выполняет вызов функции выхода. Это может привести к неожиданному поведению.

Пример

#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";
}
// Случайное выбрасывание исключения (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("Manual handling", 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);
}

Вывод:

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

Смотрите также

оборачивает функциональный объект и вызывает его при выходе из области видимости через исключение
(шаблон класса)
оборачивает функциональный объект и вызывает его при нормальном выходе из области видимости
(шаблон класса)
стандартный удалитель для unique_ptr
(шаблон класса)