std::experimental::scope_success
| Definiert in Header <experimental/scope> |
||
| template< class EF > class scope_success; |
(library fundamentals TS v3) | |
Die Klassenschablone scope_success ist ein allgemeiner Scope-Guard, der dazu bestimmt ist, seine Exit-Funktion aufzurufen, wenn ein Scope normal verlassen wird.
scope_success ist weder CopyConstructible, CopyAssignable noch MoveAssignable, jedoch kann es MoveConstructible sein, wenn EF bestimmte Anforderungen erfüllt, was das Verpacken eines scope_success in ein anderes Objekt erlaubt.
Ein scope_success kann entweder aktiv sein, d.h. ruft seine Exit-Funktion bei der Zerstörung auf, oder inaktiv, d.h. tut nichts bei der Zerstörung. Ein scope_success ist nach der Konstruktion aus einer Exit-Funktion aktiv.
Ein scope_success kann durch Aufruf von release() manuell oder automatisch (durch den Move-Konstruktor) inaktiv werden. Ein inaktives scope_success kann auch durch Initialisierung mit einem anderen inaktiven scope_success erhalten werden. Sobald ein scope_success inaktiv ist, kann es nicht wieder aktiv werden.
Ein scope_success hält effektiv ein EF und ein bool-Flag, das angibt, ob es aktiv ist, zusammen mit einem Zähler für unbehandelte Ausnahmen, der zur Erkennung verwendet wird, ob der Destruktor während des Stack-Unwindings aufgerufen wird.
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 ein neues scope_success(public member function) | |
ruft die Exit-Funktion auf, wenn der Scope normal verlassen wird, falls das scope_success aktiv ist, und zerstört dann das scope_success(public member function) | |
| operator= [gelöscht] |
scope_success ist nicht zuweisbar(öffentliche Memberfunktion) |
Modifizierer | |
macht das scope_success inaktiv(public member function) | |
[bearbeiten] Deduktionshilfen
[bearbeiten] Hinweise
Die Konstruktion eines scope_success mit dynamischer Speicherdauer kann zu unerwartetem Verhalten führen.
Die Konstruktion eines scope_success aus einem anderen scope_success, das in einem anderen Thread erstellt wurde, kann ebenfalls zu unerwartetem Verhalten führen, da der Zähler der unbehandelten Ausnahmen, der in verschiedenen Threads erhalten wurde, während der Zerstörung verglichen werden kann.
Wenn die EF, die in einem scope_success-Objekt gespeichert ist, auf eine lokale Variable der Funktion verweist, 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_success aufgerufen wird und die Exit-Funktion auslöst. 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 auf (Klassenvorlage) | |
| umschließt ein Funktions-Objekt und ruft es beim Verlassen des Geltungsbereichs durch eine Ausnahme auf (Klassenvorlage) | |
| (C++11) |
Standard-Deleter für unique_ptr (Klassen-Template) |