Namespaces
Variants

std::experimental:: scope_success

From cppreference.net

Definido en el encabezado <experimental/scope>
template < class EF >
class scope_success ;
(library fundamentals TS v3)

La plantilla de clase scope_success es un guardián de ámbito de propósito general diseñado para llamar a su función de salida cuando un ámbito se abandona normalmente.

scope_success no es CopyConstructible , CopyAssignable ni MoveAssignable , sin embargo, puede ser MoveConstructible si EF cumple ciertos requisitos, lo que permite envolver un scope_success en otro objeto.

Un scope_success puede estar activo, es decir, llama a su función de salida al destruirse, o inactivo, es decir, no hace nada al destruirse. Un scope_success está activo después de ser construido a partir de una función de salida.

Un scope_success puede volverse inactivo llamando a release() manualmente o automáticamente (por el constructor de movimiento). También se puede obtener un scope_success inactivo inicializándolo con otro scope_success inactivo. Una vez que un scope_success está inactivo, no puede volver a activarse.

Un scope_success efectivamente contiene un EF y un indicador bool que señala si está activo, junto con un contador de excepciones no capturadas utilizado para detectar si el destructor se llama durante el desenrollado de la pila.

Contenidos

Parámetros de plantilla

EF - tipo de función de salida almacenada
Requisitos de tipo
-
EF deberá ser:
-
Invocar un lvalue de std:: remove_reference_t < EF > sin argumentos deberá estar bien formado.

Funciones miembro

construye un nuevo scope_success
(función miembro pública)
llama a la función de salida cuando el ámbito se abandona normalmente si el scope_success está activo, luego destruye el scope_success
(función miembro pública)
operator=
[deleted]
scope_success no es asignable
(función miembro pública)
Modificadores
hace que el scope_success se inactive
(función miembro pública)

Guías de deducción

Notas

Construir un scope_success de duración de almacenamiento dinámico podría conducir a un comportamiento inesperado.

Construir un scope_success a partir de otro scope_success creado en un hilo diferente también podría conducir a un comportamiento inesperado, ya que el recuento de excepciones no capturadas obtenido en diferentes hilos podría compararse durante la destrucción.

Si el EF almacenado en un objeto scope_success se refiere a una variable local de la función donde está definido, por ejemplo, como una lambda que captura la variable por referencia, y esa variable se utiliza como operando de retorno en esa función, esa variable podría ya haber sido devuelta cuando se ejecuta el destructor del scope_success , llamando a la función de salida. Esto puede conducir a un comportamiento sorprendente.

Ejemplo

#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";
}
// Lanzar excepción aleatoriamente (50% de probabilidad)
void maybe_throw() {
    if (std::rand() >= RAND_MAX / 2)
        throw std::exception{};
}
int main() {
  bool exit_status{false}, did_throw{false};
  // Manejo manual al "final del ámbito"
  try {
    maybe_throw();
    exit_status = true; 
  } catch (...) { did_throw = true; }
  print_exit_status("Manejo manual", exit_status, did_throw);
  // Usando scope_exit: se ejecuta al salir del ámbito (éxito o excepción)
  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);
  // Usando scope_fail: se ejecuta solo si ocurre una excepción
  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);
  // Usando scope_success: se ejecuta solo si no ocurre excepción
  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);
}

Salida:

Manejo manual:
  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

Véase también

envuelve un objeto función y lo invoca al salir del ámbito
(plantilla de clase)
envuelve un objeto función y lo invoca al salir del ámbito mediante una excepción
(plantilla de clase)
eliminador predeterminado para unique_ptr
(plantilla de clase)