|
Hi all,
In the Rationale for Rule 15–1–3, we have:
Quote:However, syntactically, there is nothing to prevent throw; being used outside a catch handler, where there is no exception object to re-throw. This may lead to an implementation-defined program termination.
There are a couple of problems with this.
First, it't not quite right to refer to a *place* where an exception object can be re-thrown so much as it is to refer to a *time* when such an object can be re-thrown. Refer to 15.1 except.throw. For example, this program:
Code: extern "C" int printf( const char*, ... );
struct A
{
A() { (void)printf( "::A::A()\n" ); }
~A() { (void)printf( "::A::~A()\n" ); }
};
void rethrow() { throw; }
void f( ) {
try {
throw A();
}
catch (A& p) {
(void)printf( "entering f()'s handler...\n" );
rethrow();
(void)printf( "exiting f()'s handler without throwing...\n" );
}
}
int main (void) {
try {
f();
}
catch( A& p ) {
(void)printf( "exiting main()'s handler...\n" );
}
return 0;
}
... yields this output:
Code: ::A::A()
entering f()'s handler...
exiting main()'s handler...
::A::~A()
(This is specified in the Standard; this is not implementation-defined behavior.)
So the text "where there is no exception object to re-throw" should be changed to something like, "where control could pass at a time when there is no exception object to re-throw".
Second, the rationale text ends with, "This may lead to an implementation-defined program termination."
When you squint at the standardese in just the right way, this sentence is true: it *may* lead to implementation-defined behavior, but only if the non-libary part of the program does not set a terminate_handler. But given the normative text in 15.5.1 except.terminate, it would be much better to change this sentence to:
Quote:If an empty throw is used at a time when there is no exception object to re-throw, std::terminate() is implicitly called. (The stack is not unwound before this call.)
|