The introduction of int uncaught_exceptions() noexcept;
in C++17
instead of bool uncaught_exception() noexcept;
begs the question whether it is possible to have more than one exception at the same time.
According to the en.cppreference.com:
Return value
- The number of uncaught exception objects in the current thread.
I tried to imagine such a case when it would be more than one.
Having racked my brains, I came up with only one idea: throw
something in a destructor
of local variable, within the same try
block.
Yet it wouldn't do.
First, it violates the rule imposed on destructor
s forcing them to be noexcept
. Second, it can be rectified by dint of noexcept(false)
, yet it would just call terminate
instead of winding up at the catch
block.
So it does not do the trick.
Finally, throwing anything within the catch
block itself would be of the common run, nothing unusual. Since once one enters the catch
block, uncaught_exceptions()
decrements and becomes zero.
So I question if it is possible to conjure up such a case where uncaught_exceptions()
would return more than 1
?
The hint is given on the site you link:
Sometimes it's safe to throw an exception even while
std::uncaught_exception() == true
. For example, if stack unwinding causes an object to be destructed, the destructor for that object could run code that throws an exception as long as the exception is caught by some catch block before escaping the destructor.
Using this as recipe: We throw an exception, in a destructor of an object that is destroyed during stack unwinding we throw another one that is immediately catched, but while it is in the air we look at the number of uncaught exceptions (can be done via another object's destructor, tracker
):
#include <iostream>
#include <exception>
struct tracker {
~tracker() {
std::cout << std::uncaught_exceptions() << "\n";
}
};
struct foo {
~foo() {
try {
tracker t;
throw 123;
} catch(...) {
std::cout << std::uncaught_exceptions() << "\n";
}
}
};
int main() {
try {
foo f;
throw 42;
} catch(...) {}
}
Output:
2
1
The crucial point is that the second exception does not escape foo
s destructor. And to see both we need to call uncaught_exceptions
before the catch
block in foo
s destructor is entered. Thats why I used tracker
. Once the catch
block is entered it returns again 1
.
I wouldn't know how to observe uncaught_exception == 2
without this double layer of stack-unwinding. Perhaps thats also a reason this was overlooked at first and only fixed in c++17. On the other hand, more layers could be added to have also uncaught_exception > 2
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With