Re: Templated throw() specifications.
On Jun 4, 8:22 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
You seem to misunderstand throw specifications. They are enforced at
run-time not at compile time. If an exception wants to unwind the stack
past a function from which it is not allowed to escape according to the
exception specification, then the function unexpected() is called.
I did misunderstand; I am so used to compilers enforcing it in Java
that I just kind of assumed C++ would handle them similarly.
Fascinating! I had no idea that you could use set_unexpected() to
change the behavior. In fact, long ago I had once thrown an exception
from a function with a different throw() specification, and the
program terminated. I had immediately assumed that it was because
perhaps the compiler had performed some optimizations or something and
some weird internal error occurred when I threw an exception it didn't
expect to have to handle when compiling the code. I didn't even look
into it any further, that event just made me paranoid and started me
down the road of always using throw() specifications and sticking to
them (which I guess isn't a bad thing but I did it for the wrong
reasons).
So, when I test this with GCC 4.1.2:
class A { };
class B { };
void f1 () throw (A) { throw B(); }
void f2 () { throw B(); }
A call to f1() leads to unexpected() being called, as expected (heh).
However, a call to f2() works just fine. It seems that not specifying
throw(...) at all is the same as saying "this function can throw
anything it wants". That's correct, right? It's not a GCC quirk?
Now, in that case, I still have my original question although for
different reasons. I'd like to be able to enforce strict exception
handling at run-time, and so I'd need to specify the exception type
that the "callback function" can throw in that template class. Right?
Is there a better way to do that? If my goal is to enforce that kind
of exception handling, and my situation is like what it was in my
original post (example at end of this post for reference), is that the
way to do it?
If it really
doesn't matter (and won't matter in C++0x either), then the above
template stuff is completely unnecessary since I can just declare
Call() with no exception specification at all and not have to deal
with it.
By and large, throw specifications can be considered useless with the
notable exception of throw().
Do you think that they are reliably useful for checking for developer
errors at runtime, at least?
Thanks,
Jason
=== BEGIN EXAMPLE ===
#include <iostream>
#include <string>
using namespace std;
void function () throw (string) {
throw string("Oops");
}
template <class EX> class A {
public:
typedef void (* FN) ();
explicit A (FN f) : f_(f) { }
void Call () throw (EX) { f_(); }
private:
FN f_;
};
int main () {
A<string> a(&function);
try {
a.Call();
} catch (const string &s) {
cout << s << endl;
}
}
=== END EXAMPLE ===
The goal of the above is to allow the callback function to throw any
exception it wants (not necessarily derived from std::exception, so
simply specifying that is not an option), and still have the generated
template code for A have the correct throw() specifier for A::Call().