The main problem with throwing exceptions from destructor is that in the moment when destructor is called another exception may be "in flight" (std::uncaught_exception() == true
) and so it is not obvious what to do in that case. "Overwriting" the old exception with the new one would be the one of the possible ways to handle this situation. But it was decided that std::terminate
(or another std::terminate_handler
) must be called in such cases.
C++11 introduced nested exceptions feature via std::nested_exception
class. This feature could be used to solve the problem described above. The old (uncaught) exception could be just nested into the new exception (or vice versa?) and then that nested exception could be thrown. But this idea was not used. std::terminate
is still called in such situation in C++11 and C++14.
So the questions. Was the idea with nested exceptions considered? Are there any problems with it? Isn't the situation going to be changed in the C++17?
The problem you cite happens when your destructor is being executed as part of the stack unwinding process (when your object was not created as part of stack unwinding)1, and your destructor needs to emit an exception.
So how does that work? You have two exceptions in play. Exception
X
is the one that's causing the stack to unwind. ExceptionY
is the one that the destructor wants to throw.nested_exception
can only hold one of them.So maybe you have exception
Y
contain anested_exception
(or maybe just anexception_ptr
). So... how do you deal with that at thecatch
site?If you catch
Y
, and it happens to have some embeddedX
, how do you get it? Remember:exception_ptr
is type-erased; aside from passing it around, the only thing you can do with it is rethrow it. So should people be doing this:I don't see a lot of people doing that. Especially since there would be an exceedingly large number of possible
X
-es.1: Please do not use
std::uncaught_exception() == true
to detect this case. It is extremely flawed.