When I'm trying the following code:
#include <thread>
struct foo
{
~foo() noexcept(false) { throw 0; }
};
void func()
try
{
static foo f;
}
catch(...)
{
}
int main()
{
std::thread t{func};
t.join();
}
the compiler gives me the following error:
terminating due to uncaught exception of type int
I then went to the standard to find a rule that would prohibit the above example from working, but I couldn't find that; and simply that's my problem.
The rule that I think it applies here is [except.handle]/11; this bullet says:
Exceptions thrown in destructors of objects with static storage duration or in constructors of objects associated with non-block variables with static storage duration are not caught by a function-try-block on the main function.
Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a function-try-block on the initial function of the thread.
I think the first part of this bullet is not applicable because the function-try-block is on function func
not main
function. Also, I see the second part of the bullet is not applicable because it talks about thread objects not static objects.
Was it the above rule that prohibited my example from working? If not, what is the correct rule from the standard to apply here?
The relevant wording is in [basic.start.term] p3:
If the destruction of an object with static or thread storage duration exits via an exception, the function
std::terminate
is called ([except.terminate]).
The subsequent wording in [except.handle] p11 which you have found could be a note, assuming that the other content of the paragraph concerning construction is also covered elsewhere (it most likely is).
The reader has no reason to believe that a function-try-block for main
would catch the exception when reading this paragraph; it is redundant.