Date: Thu, 11 Jan 2024 10:42:02 -0500
On Thu, Jan 11, 2024 at 10:24 AM Andrey Semashev via Std-Proposals <
std-proposals_at_[hidden]> 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
<https://quuxplusone.github.io/blog/2018/08/11/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://www.google.com/search?q=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");
}
}
std-proposals_at_[hidden]> 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
<https://quuxplusone.github.io/blog/2018/08/11/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://www.google.com/search?q=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");
}
}
Received on 2024-01-11 15:42:18