Namespaces
Variants

std::experimental:: scope_success

From cppreference.net

Défini dans l'en-tête <experimental/scope>
template < class EF >
class scope_success ;
(library fundamentals TS v3)

Le modèle de classe scope_success est un garde de portée à usage général conçu pour appeler sa fonction de sortie lorsqu'une portée est quittée normalement.

scope_success n'est pas CopyConstructible , CopyAssignable ou MoveAssignable , cependant, il peut être MoveConstructible si EF satisfait certaines exigences, ce qui permet d'encapsuler un scope_success dans un autre objet.

Un scope_success peut être soit actif, c'est-à-dire qu'il appelle sa fonction de sortie lors de la destruction, soit inactif, c'est-à-dire qu'il ne fait rien lors de la destruction. Un scope_success est actif après avoir été construit à partir d'une fonction de sortie.

Un scope_success peut devenir inactif en appelant release() sur celui-ci manuellement ou automatiquement (par le constructeur de déplacement). Un scope_success inactif peut également être obtenu en l'initialisant avec un autre scope_success inactif. Une fois qu'un scope_success est inactif, il ne peut plus redevenir actif.

Un scope_success contient effectivement un EF et un indicateur bool indiquant s'il est actif, ainsi qu'un compteur d'exceptions non attrapées utilisé pour détecter si le destructeur est appelé lors du déroulement de pile.

Table des matières

Paramètres du modèle

EF - type de fonction de sortie stockée
Exigences de type
-
EF doit être soit :
-
L'appel d'une lvalue de std:: remove_reference_t < EF > sans argument doit être bien formé.

Fonctions membres

construit un nouveau scope_success
(fonction membre publique)
appelle la fonction de sortie lorsque la portée est quittée normalement si le scope_success est actif, puis détruit le scope_success
(fonction membre publique)
operator=
[deleted]
scope_success n'est pas assignable
(fonction membre publique)
Modificateurs
rend le scope_success inactif
(fonction membre publique)

Guides de déduction

Notes

La construction d'un scope_success de durée de stockage dynamique peut entraîner un comportement inattendu.

La construction d'un scope_success à partir d'un autre scope_success créé dans un thread différent peut également conduire à un comportement inattendu puisque le nombre d'exceptions non capturées obtenu dans différents threads peut être comparé lors de la destruction.

Si le EF stocké dans un objet scope_success fait référence à une variable locale de la fonction où il est défini, par exemple comme une lambda capturant la variable par référence, et que cette variable est utilisée comme opérande de retour dans cette fonction, cette variable pourrait déjà avoir été retournée lorsque le destructeur du scope_success s'exécute, appelant la fonction de sortie. Cela peut conduire à un comportement surprenant.

Exemple

#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";
}
// Lance aléatoirement une exception (50% de chance)
void maybe_throw() {
    if (std::rand() >= RAND_MAX / 2)
        throw std::exception{};
}
int main() {
  bool exit_status{false}, did_throw{false};
  // Gestion manuelle à la "fin de portée"
  try {
    maybe_throw();
    exit_status = true; 
  } catch (...) { did_throw = true; }
  print_exit_status("Manual handling", exit_status, did_throw);
  // Utilisation de scope_exit : s'exécute à la sortie de portée (succès ou 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);
  // Utilisation de scope_fail : s'exécute uniquement si une exception se produit
  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);
  // Utilisation de scope_success : s'exécute uniquement si aucune exception ne se produit
  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);
}

Sortie :

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

Voir aussi

encapsule un objet fonction et l'invoque en quittant la portée
(modèle de classe)
encapsule un objet fonction et l'invoque en quittant la portée via une exception
(modèle de classe)
suppresseur par défaut pour unique_ptr
(modèle de classe)