
3) Support exception wrapping on the module boundary (so that module has to care only for exceptions of the modules it uses directly) - and this I still don't know how to do as I have no good ideas for wrapping which will not loose a lot of data on the original exception.
Wrapping is not a good idea. If a module can handle an exception -- great, if not -- it shouldn't interfere (by changing the original exception's type.)
I do not agree. Consider module responsible for providing data to the application, building the "data model". It might fail to load the data because of loss of connection do database for example. Now if your philosophy was used the "view module" would have to catch for example database_error when loading the data model. Everything fine except that if I change the database to a different one the exception thrown by database controller will likely change - after all what are the chances that different vendors use the same class - other then generic std::exception - as base class? And thus the "view module" will have to switch to "database_2_error". But what about changing the "data module" to provide data from a local file? What if it provided data from the local file and database at the same time? Each such change requires to change the "view module" to catch appropriate exception. This just does not seem right. And after all it reveals implementation details of the "data module". The "data module" should rather throw its own exception ("load_error") regardless of the underlying raw data provider (file, database 1, database 2, ...). Then "view module" would be independent on the internals of implementation of the "data module". But that requires "data module" to cache the exceptions of raw data provider and throw load_error instead. This obviously leads to loss of diagnostics data (after all the error may be due to database authorization error and someone has to correct the user/password). That is way I thing that some kind of wrapping/chaining/nesting or how you call it would be useful here. It would make the "view module" independent on the internals of "data module" however full information will be still available and could be for example logged. Or in some weird special cases the "view module" could even investigate the inner exception and deal with it - however it would not have to. I agree that inheriting would be better here. But this in most cases cannot be done dynamically or would lead to enormous large code. If we wanted load_error to inherit from the raw data provider error then we would have to declare base_load_error and then file_load_error, database_1_load_error and so on... However this is not even near the end. This would work only if the raw data provides modules declared exact types of thrown objects and did not abuse that declaration. And then file provider could throw file_does_not_exist, access_denied or file_corrupted, or inherited from file_error then "data module" would have to catch them as well and provide appropriate load_errors (here we start to think about making base_load_error and template_load_error : public base_load_error). Also we would have to require from the exception classes that they were copy-constructible and that such copies are equivalent. This puts a lot of requirements on the providers modules. And adding an additional exception in the lowest module propagates to massive changes in upper modules. That is why I think wrapping/chaining/nesting is better. Currently we can chain exceptions with boost::exception by constructing a new boost::exception and injecting to it error_info<struct nested_exception_tag, exception_ptr> with exception taken by current_exception. However at the catch site there is little we can do with exception_ptr without rethrowing it to catch it and print diagnostic data. How about allowing diagnostic data for exception_ptr? Adam Badura