Discussion
Team LiB
Previous Section Next Section

Discussion

In brief, don't bother with exception specifications. Even experts don't bother. The main problems with exception specifications are that they're only "sort of" part of the type system, they don't do what most people think, and you almost always don't want what they actually do.

Exception specifications aren't part of a function's type, except when they are. They form a shadow type system whereby writing an exception specification is variously:

  • Illegal: In a typedef for a pointer to function.

  • Allowed: In the identical code without the typedef.

  • Required: In the declaration of a virtual function that overrides a base class virtual function that has an exception specification.

  • Implicit and automatic: In the declaration of the constructors, assignment operators, and destructors when they are implicitly generated by the compiler.

A common but nevertheless incorrect belief is that exception specifications statically guarantee that functions will throw only listed exceptions (possibly none), and enable compiler optimizations based on that knowledge.

In fact, exception specifications actually do something slightly but fundamentally different: They cause the compiler to inject additional run-time overhead in the form of implicit try/catch blocks around the function body to enforce via run-time checking that the function does in fact emit only listed exceptions (possibly none), unless the compiler can statically prove that the exception specification can never be violated in which case it is free to optimize the checking away. And exception specifications can both enable and prevent further compiler optimizations (besides the inherent overhead already described); for example, some compilers refuse to inline functions that have exception specifications.

Worst of all, however, is that exception specifications are a blunt instrument: When violated, by default they immediately terminate your program. You can register an unexpected_handler, but it's highly unlikely to help you much because you get exactly one global handler and the only way the handler could avoid immediately calling terminate would be to rethrow an exception that is permissiblebut because you have only one handler for your whole application, it's hard to see how it could do useful recovery or usefully know what exceptions might be legal without trivializing exception specifications altogether (e.g., following the discipline of having all exception specifications allow some general UnknownException eliminates any advantage that having an exception specification might have had in the first place).

You generally can't write useful exception specifications for function templates anyway, because you generally can't tell what exceptions the types they operate on might throw.

Paying a performance overhead in exchange for enforcements that are nearly always useless because they are fatal if they ever fire is an excellent example of a premature pessimization (see Item 9).

These is no easy fix for the problems described in this Item. In particular, the problems are not easily solved by switching to static checking. People often suggest switching from dynamically checked exception specifications to statically checked ones, as provided in Java and other languages. In short, that just trades one set of problems for another; users of languages with statically checked exception specifications seem to equally often suggest switching to dynamically checked ones.

    Team LiB
    Previous Section Next Section