10

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.)

Taral
  • 327
  • 1
  • 15
  • An important thing to note is that compilers cannot always see the definition. – R. Martinho Fernandes Aug 27 '13 at 17:16
  • 1
    I think a big reason is that it would break a lot of good template code. – Fred Larson Aug 27 '13 at 17:17
  • (And if you want to push this further, why would a compiler even allow a function to access variables that don't appear in the function declaration?) – R. Martinho Fernandes Aug 27 '13 at 17:18
  • 4
    Because Java. And I'm serious. –  Aug 27 '13 at 17:19
  • 4
    @R.MartinhoFernandes: I don't see why the compiler would need the definitions. A function conforms to its exception specification iff all of its statements which may result in exceptions which are not specified are surrounded by appropriate try-catch blocks. Since the compiler has to know the declarations of all functions called within anyway, it also knows what they are allowed to throw. Accessing global variables is not about type-safety (and this is not about imperative vs. functional programming). – Taral Aug 27 '13 at 17:37
  • 1
    @Taral No, compiler does not have to know, sometimes does not know and does not have a way of knowing. Consider dynamic loading. – lapk Aug 27 '13 at 17:39
  • 1
    @Taral Something like this might be feasible (but not necessarily desirable) if C++ were starting from 0. As it is, there are too many functions floating around which don't have exception specifiers, but which won't throw. – James Kanze Aug 27 '13 at 17:43
  • possible duplicate of [Why noexcept is not enforced at compile time?](http://stackoverflow.com/questions/14593333/why-noexcept-is-not-enforced-at-compile-time) – Jerry Coffin Aug 27 '13 at 18:17
  • @PetrBudnik do you mean `dlopen`/`dlsym`? – curiousguy Oct 06 '15 at 01:45

2 Answers2

11

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.

Casey
  • 41,449
  • 7
  • 95
  • 125
James Kanze
  • 150,581
  • 18
  • 184
  • 329
-1

If the function f() throw(int) called the function g() throw(int, double) what would happen?

A compile time check would prevent your function from calling any other function with a less strict throw specifier which would be a huge pain.

asymptoticFault
  • 4,491
  • 2
  • 19
  • 24
  • 1
    if the function `int f()` returned the result of `double g()` without conversion, not having this raise an error would not be a huge pain, but, well, an error. And I said nothing about making anything mandatory; one could always declare `f()` without a `throw` specifier ... – Taral Aug 27 '13 at 17:39