We are now going to assume that if a function returns without throwing an exception, the operation has succeeded. If the function throws, it obviously failed. The objective now is to get rid of the explicit call to commit() and instead detect whether the destructor of a ScopeGuard is executed because an exception was thrown, or because the function returned normally.
There are two parts to this implementation. The first part is specifying when we want the action to be taken. The cleanup guard must be executed regardless of how we exit the scope. The rollback guard is executed only in case of a failure. For completeness, we can also have a guard that is executed only if the function has succeeded. The second part ...