SCOPE#
-
SCOPE(kind)#
Automatically runs code when a scope is exited (
SCOPE(exit)), exited by means of an exception (SCOPE(fail)), or exited normally (SCOPE(success)).The code controlled by
SCOPE(exit)andSCOPE(fail)must not throw. In debug builds (NDEBUGnot defined) those lambdas are invoked viathrow_proofusing theSCOPEcall-site location; in release builds they are called directly. The code controlled bySCOPE(success)may throw. In all cases the controlled code must returnvoid(enforced at compile time).SCOPE(exit)runs its code at the natural termination of the current scope. Example:// SCOPE(exit) runs the lambda upon the termination of the current scope. bool done = false; { SCOPE(exit) { done = true; }; EXPECT(!done, "SCOPE_EXIT should not run early."); } EXPECT(done);
SCOPE(fail)runs its code if and only if the current scope is left by means of throwing an exception. Example:bool done = false; { SCOPE(fail) { done = true; }; EXPECT(!done, "SCOPE_FAIL should not run early."); } EXPECT(!done); try { SCOPE(fail) { done = true; }; EXPECT(!done); throw 42; } catch (...) { EXPECT(done); }
Finally,
SCOPE(success)runs its code if and only if the current scope is left by normal flow (as opposed to by an exception). Example:bool done = false; { SCOPE(success) { done = true; }; EXPECT(!done); } EXPECT(done); done = false; try { SCOPE(success) { done = true; }; EXPECT(!done); throw 42; } catch (...) { EXPECT(!done); }
If two or more
SCOPEdeclarations are present in the same scope, they will take effect in the reverse order of their lexical order. Example:int counter = 0; { SCOPE(exit) { EXPECT(counter == 2); counter = 0; }; SCOPE(success) { EXPECT(counter == 1); ++counter; }; SCOPE(exit) { EXPECT(counter == 0); ++counter; }; EXPECT(counter == 0); } EXPECT(counter == 0);
See Also: https://en.cppreference.com/w/cpp/experimental/scope_exit, https://en.cppreference.com/w/cpp/experimental/scope_fail, https://en.cppreference.com/w/cpp/experimental/scope_success