Ah I see, like
struct B { ~B( ) noexcept( false ) { throw ...; } };
struct A { B b; ~A( ) noexcept( false ) { throw...;} };
I guess the saving grace is that most C++ devs are aware of what could throw in a destructor because it is rare and C++ 11 made this more difficult. Just don't and design around it. If the destructor fails use it as a choice to terminate or ignore.
Yeah. But when people start writing wrappers like SCOPE_EXIT that call user code inside destructors, suddenly the users of those wrappers don't have any way to know they can't throw exceptions.
scope_exit is just not very idiomatic C++. If used, It's for quick'n'dirty I'm too rushed to wrap it in a class times.
It's use in C++ implies that you are worrying about something at the wrong abstraction level too.
With that though, I would think that the default > c++11 implicit noexcept is proper. Crash hard when an exception is thrown and maybe even static assert on the result of noexcept( on_exit_cb ) so that it gives a compile error, lambda's can be noexcept and c functions cannot throw(thinking fclose and friends)
The people who use SCOPE_EXIT are responsible for making sure no exceptions are thrown (well, that any exceptions that get thrown are swallowed before they trigger std::terminate).
If that’s not possible, they have to use a different approach.
I guess the saving grace is that most C++ devs are aware of what could throw in a destructor because it is rare and C++ 11 made this more difficult. Just don't and design around it. If the destructor fails use it as a choice to terminate or ignore.