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.