On 30/05/2022 11:59, Emil Dotchevski wrote:
The correct use of exception handling in C++ is to let exceptions propagate unmolested by default; there is no explicit checking for errors after calling a function that may throw. You catch only where the error can be handled and the program can restore normal operations.
The problem with this definition is that it is too vague (although that is somewhat of necessity due to being general advice). Someone can, by the letter (but not the spirit) of that rule, argue that their program can resume normal operations immediately outside of that function call (to e.g. handle a "file not found" or a "input string was not a number" type of error that really ought to be checked a different way).
And while it is true that unhandled exceptions terminate the program, that is always a logic error, programs should handle all exceptions that may be thrown. Terminating the program when an exception is thrown is valid only under -fno-exceptions (in Boost you'd do that by providing a suitable definition for boost::throw_exception). >
The argument for the "truly exceptional" case is that since exceptions should never normally happen, there's no reasonable way to resume normal operations (e.g. data structures might be in an inconsistent state if an exception was thrown mid-mutation). If everything uses the strong exception guarantee all the way down, or you can otherwise guarantee that you've destroyed all data structures that might have been mutated by the exception-generating codepath, then it may be safe to continue. But this is a more difficult bar to meet than "exceptions should never happen, just die" -- and it's easy to get it wrong and continue running with inconsistent data that acts as a time-bomb for later misbehaviour or incorrect calculations.