Namespaces
Variants

std::experimental:: scope_success

From cppreference.net

Определено в заголовочном файле <experimental/scope>
template < class EF >
class scope_success ;
(Technical Specification библиотеки fundamentals v3)

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

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

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

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

Объект scope_success фактически содержит EF и bool флаг, указывающий, активен ли он, вместе со счётчиком неперехваченных исключений, используемым для определения, вызывается ли деструктор во время раскрутки стека.

Содержание

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

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

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

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

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

Примечания

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

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

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

Пример

#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
(шаблон класса)