On Thu, Jan 11, 2024 at 10:24 AM Andrey Semashev via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On 1/11/24 17:42, Frederick Virchanza Gotham via Std-Proposals wrote:
> Today I wrote the following code; look at how I use a stack variable
> "exception_was_thrown":
>
>     bool exception_was_thrown = false;
>
>     try
>     {
>             Entry_Point_Thread_Terminal_Proper(str_comport);
>             rs232win.Close();  // This is harmless no-op if the port isn't open
>     }
>     catch(std::exception const &e)
>     {
>         exception_was_thrown = true;
>         LogText(  std::string( "Exception (" ) + e.what() + ")"  );
>     }
>     catch(...)
>     {
>         exception_was_thrown = true;
>         LogText("Unknown Exception");
>     }
>
>     if ( exception_was_thrown )
>     {
>         pdialog->CallAfter(&Dialog_Main::CallTerminateFullRun);
>     }
>
> Upon the catching of an exception, I want some common code to be
> executed for all of the 'catch' clauses.

Why not use a scope guard?

Right. You can do this pretty naturally using the `Auto` macro, for example:
https://godbolt.org/z/b5zvKPb61
The only trick is that the way to express "Do `OnTheWayOut` at the end of every catch-block" is really to express "Do an early exit at the end of the try block, and then let all the catch blocks fall through into `OnTheWayOut`." That's not as structured as we'd really like, but it's okay.

void test(int x) {
printf("Testing with x=%d\n", x);
try {
Auto(
if (std::uncaught_exceptions() >= 1)
puts(" CallTerminateFullRun");
);
puts(" In try body");
throw_if(x);
puts(" Still in try body");
return;
} catch (const std::exception& ex) {
printf(" Caught std::exception with message %s\n", ex.what());
} catch (...) {
puts(" Caught unknown exception");
}
puts(" OnTheWayOut");
}

Another, more structured, way to merge the catch blocks is to use a Lippincott function:
https://godbolt.org/z/dfo797fao
Here I've written it using P2927 `std::try_cast` as proposed for C++26 (note that I think there's a good chance we'll rename it to `std::exception_cast`), but you could do it by manually `rethrow_exception`'ing and `catch`ing just as well.
(This is exactly what Ville just said, as I was in the process of typing this up.)

void handle(std::exception_ptr p) {
if (auto *ex = std::try_cast<std::exception>(p)) {
printf(" Caught std::exception with message %s\n", ex->what());
} else {
puts(" Caught unknown exception");
}
}

void test(int x) {
printf("Testing with x=%d\n", x);
try {
puts(" In try body");
throw_if(x);
puts(" Still in try body");
return;
} catch (...) {
puts(" CallTerminateFullRun");
handle(std::current_exception());
puts(" OnTheWayOut");
}
}