-
Notifications
You must be signed in to change notification settings - Fork 762
Description
gsl::finally in name, API, and documentation purports to allow arbitrary code to be executed at scope exit, however in practice it executes the provided function within its noexcept(true) destructor which results in a runtime crash if the provided action throws.
In name, there is an implied understanding for gsl::finally, which borrows the "finally" concept from C-based languages, to execute arbitrary, even throwing code. This behavior models what "finally" means in other C-based languages where there isn't a constraint on code in the finally block being non-throwing.
In API, gsl::finally will accept a throwing action without indication/enforcement that the action must not throw even though in practice and at runtime, this is a requirement otherwise the program terminates:
gsl::finally([] { throw 1; }); // valid code which compiles and crashes at runtime
In documentation, it documents that "something gets run", implying any arbitrary code is fine.
`final_action` allows you to ensure something gets run at the end of a scope.
In summary, programmers do want a utility to help execute code at scope exit.
First we must decide if we should provide such a utility or if not, and what alternative should exist if any to make code such as:
if (...) Update(); return;
if (...) Update(); return;
if (...) Update(); return;
which would be a reason a programmer would seek out gsl::finally as a utility to execute Update prior to returning without having to manually write it out n-many times.
Next, we must decide if we place exception constraints on gsl::finally.
We may decide to truly allow arbitrary code to execute in gsl::finally, in which case we could specify its destructor's noexcept(false) or based on a template parameter or whether the provided action throws.
If we instead decide to retain gsl::finally's noexcept execution of the action, we should decide how to solve for the problem of:
gsl::finally([] { throw 1; };
where we know at compile time such code is invalid and will terminate at runtime. Can we enforce this at compile time? Yes, i.e. by requiring std::is_nothrow_invocable on the function.
Finally, in addition to compile time enforcement, the documentation (and possibly the name) should be updated to make it clear that gsl::finally can only be used with non-throwing code and the user must ensure the supplied action must not throw (else the program will terminate)
Metadata
Metadata
Assignees
Labels
Type
Projects
Status