Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are C++ exception specifications not checked at compile-time?

I just read that in the C++11 standard revision, exception specifications were deprecated. I previously thought specifying what your functions may throw is good practice, but apparently, not so.

After reading Herb Stutter's well-cited article, I cannot help but wonder: why on earth are exception specifications implemented the way they are, and why has the committee decided to deprecate them instead of having them checked at compile-time? Why would a compiler even allow an exception to be thrown which doesn't appear in the function definition? To me, this all sounds like saying "You probably shouldn't specify your function return type, because when you specify int f(), but return 3.5; inside of it, your program will likely crash." (i. e., where is the conceptual difference from strong typing?)

(For the lack of exception specification support in typedefs, given that template syntax is probably Turing-complete, implementing this sounds easy enough.)

like image 500
Taral Avatar asked Aug 27 '13 17:08

Taral


1 Answers

The original reason was that it was deemed impossible to reliably check given the body of existing code, and the fact that no specifier means anything can throw. Which means that if static checking was in force, the following code wouldn't compile:

double
safeSquareRoot( double d ) throw()
{
    return d > 0.0 ? sqrt( d ) : 0.0;
}

Also, the purpose of exceptions are to report errors over a great distance, which means that the intermediate functions shouldn't know what the functions they call might throw. Requiring exception specifiers on them would break encapsulation.

The only real case where a function needs to know about the exceptions that might occur is to know what exceptions cannot occur. In particular, it is impossible to write thread safe code unless you can be guaranteed that some functions will never throw. Even here, static checking isn't acceptable, for the reasons explained above, so the exception specification is designed to work more like an assertion that you cannot disactivate: when you write throw(), you get more or less the equivalent of an assertion failure if the function is terminated by an exception.

The situation in Java is somewhat different. In Java, there are no real out parameters, which means that if you can't use return codes if the function also has a return value. The result is that exceptions are used in a lot of cases where a return code would be preferable. And these, you do have to know about, and handle immediately. For things that should really be exceptions, Java has java.lang.RuntimeException (which isn't checked, statically or otherwise). And it has no way of saying that a function cannot ever throw an exception; it also uses unchecked exceptions (called Error) in cases where aborting the program would be more appropriate.

like image 129
James Kanze Avatar answered Sep 30 '22 20:09

James Kanze