std::experimental:: scope_success
|
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 :
|
||
|
-
|
||
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) |
|
|
(C++11)
|
suppresseur par défaut pour
unique_ptr
(modèle de classe) |