Should I use an exception specifier in C++?
No.
Here are several examples why:
Template code is impossible to write with exception specifications,
template<class T> void f( T k ) { T x( k ); x.x(); }
The copies might throw, the parameter passing might throw, and
x()
might throw some unknown exception.Exception-specifications tend to prohibit extensibility.
virtual void open() throw( FileNotFound );
might evolve into
virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );
You could really write that as
throw( ... )
The first is not extensible, the second is overambitious and the third is really what you mean, when you write virtual functions.
Legacy code
When you write code which relies on another library, you don't really know what it might do when something goes horribly wrong.
int lib_f(); void g() throw( k_too_small_exception ) { int k = lib_f(); if( k < 0 ) throw k_too_small_exception(); }
g
will terminate, whenlib_f()
throws. This is (in most cases) not what you really want.std::terminate()
should never be called. It is always better to let the application crash with an unhandled exception, from which you can retrieve a stack-trace, than to silently/violently die.Write code that returns common errors and throws on exceptional occasions.
Error e = open( "bla.txt" ); if( e == FileNotFound ) MessageUser( "File bla.txt not found" ); if( e == AccessDenied ) MessageUser( "Failed to open bla.txt, because we don't have read rights ..." ); if( e != Success ) MessageUser( "Failed due to some other error, error code = " + itoa( e ) ); try { std::vector<TObj> k( 1000 ); // ... } catch( const bad_alloc& b ) { MessageUser( "out of memory, exiting process" ); throw; }
Nevertheless, when your library just throws your own exceptions, you can use exception specifications to state your intent.
Avoid exception specifications in C++. The reasons you give in your question are a pretty good start for why.
See Herb Sutter's "A Pragmatic Look at Exception Specifications".