Subject: Re: [boost] [exception] Virtual inheritance with nodefaultconstructors
From: Adam Badura (abadura_at_[hidden])
Date: 2009-05-14 02:26:02
>> 3) Support exception wrapping on the module boundary (so that module has
>> care only for exceptions of the modules it uses directly) - and this I
>> 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
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
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
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?