std::experimental::scope_exit
| Definiert in Header <experimental/scope> |
||
| template< class EF > class scope_exit; |
(library fundamentals TS v3) | |
Die Klassentemplate scope_exit ist ein Allzweck-Scope-Guard, der dazu bestimmt ist, seine Exit-Funktion aufzurufen, wenn ein Geltungsbereich verlassen wird.
scope_exit ist weder CopyConstructible, CopyAssignable noch MoveAssignable, jedoch kann es MoveConstructible sein, wenn EF bestimmte Anforderungen erfüllt, was das Einpacken eines scope_exit in ein anderes Objekt ermöglicht.
Ein scope_exit kann entweder aktiv sein, d.h. es ruft seine Exit-Funktion bei der Zerstörung auf, oder inaktiv, d.h. es tut nichts bei der Zerstörung. Ein scope_exit ist nach der Konstruktion aus einer Exit-Funktion aktiv.
Ein scope_exit kann inaktiv werden, indem release() manuell oder automatisch (durch den Move-Konstruktor) darauf aufgerufen wird. Ein inaktives scope_exit kann auch durch Initialisierung mit einem anderen inaktiven scope_exit erhalten werden. Sobald ein scope_exit inaktiv ist, kann es nicht wieder aktiv werden.
Ein scope_exit hält effektiv eine EF und ein bool Flag, das anzeigt, ob es aktiv ist.
Inhalt |
[bearbeiten] Template-Parameter
| EF | - | Typ der gespeicherten Exit-Funktion |
| Typanforderungen | ||
-EF muss entweder sein:
| ||
| -Der Aufruf eines lvalue von std::remove_reference_t<EF> ohne Argument muss wohlgeformt sein. | ||
[bearbeiten] Member-Funktionen
konstruiert einen neuen scope_exit(public member function) | |
ruft die Exit-Funktion auf, wenn der Geltungsbereich verlassen wird und der scope_exit aktiv ist, zerstört dann den scope_exit(public member function) | |
| operator= [gelöscht] |
scope_exit ist nicht zuweisbar(öffentliche Memberfunktion) |
Modifizierer | |
macht den scope_exit inaktiv(public member function) | |
[bearbeiten] Deduktionshilfen
[bearbeiten] Hinweise
Das Erstellen eines scope_exit mit dynamischer Speicherdauer kann zu unerwartetem Verhalten führen.
Wenn die EF, die in einem scope_exit-Objekt gespeichert ist, sich auf eine lokale Variable der Funktion bezieht, in der sie definiert ist, z.B. als Lambda, das die Variable per Referenz erfasst, und diese Variable als Rückgabeoperand in dieser Funktion verwendet wird, könnte diese Variable bereits zurückgegeben worden sein, wenn der Destruktor des scope_exit ausgeführt wird und die Exit-Funktion aufruft. Dies kann zu überraschendem Verhalten führen.
[bearbeiten] Beispiel
#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"; } // Randomly throw an exception (50% chance) void maybe_throw() { if (std::rand() >= RAND_MAX / 2) throw std::exception{}; } int main() { bool exit_status{false}, did_throw{false}; // Manual handling at "end of scope" try { maybe_throw(); exit_status = true; } catch (...) { did_throw = true; } print_exit_status("Manual handling", exit_status, did_throw); // Using scope_exit: runs on scope exit (success or 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); // Using scope_fail: runs only if an exception occurs 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); // Using scope_success: runs only if no exception occurs 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); }
Ausgabe
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
[bearbeiten] Siehe auch
| umschließt ein Funktions-Objekt und ruft es beim Verlassen des Geltungsbereichs durch eine Ausnahme auf (Klassenvorlage) | |
| umschließt ein Funktions-Objekt und ruft es beim normalen Verlassen des Geltungsbereichs auf (Klassenvorlage) | |
| (C++11) |
Standard-Deleter für unique_ptr (Klassen-Template) |