From: Peter Dimov (pdimov_at_[hidden])
Date: 2002-11-21 08:46:23
From: "Beman Dawes" <bdawes_at_[hidden]>
> Boost libraries often define exception classes, usually derived from the
> standard library exception hierarchy. Users sometimes ask for further
> refinement, so the library ends up with its own hierarchy.
> For example, the Filesystem library started out with
> boost::filesystem::filesystem_error, but reviewers asked for more specific
> exceptions at least for the most common errors (like "file not found".)
> suggested plan was to add one or two derived error types now, and more as
> experience dictates.
I don't have filesystem_error handy as I write this but from what I
remember, it was impossible to handle a filesystem_error in a portable
manner, for any nontrivial definition of "handle". The only information it
provides is an implementation-defined error code and an
implementation-defined explanatory message. The former cannot be used
portably to affect code flow; the latter, in the general case, cannot be
presented to the user. Sorry if this sounds too harsh, but the only goal of
the Filesystem library is to provide a _portable layer_; hence, the library
_must_ report errors in a portable manner.
My suggestion is to adopt errno codes as a way of portably identifying the
error, and return the string representation of the corresponding macro from
what() (i.e. ENOMEM, EACCES, ENOTDIR.)
In other words, filesystem exceptions should probably derive from
virtual char const * what() throw();
int error() const;
(errno_exception comes in handy when one needs to report pthread failure or
other POSIX failures, too) although other solutions are possible.
Note that the above is a good counterexample for the suggestion that what()
should return typeid().name().
> That works well for callers who know exactly what exception types will be
> thrown, but also implies that libraries like Boost.Test which try to catch
> specific exception types (for better error reporting) have to be
> continually updated to reflect new boost exceptions being added. An
> exception class which was self-explanatory would be better for these uses.
> I try to cope with that need by a lengthy what() message.
Libraries that only need to report the error should not need to catch
specific types. The only reason for the current (sad) situation is that the
what() string is not well defined, and hence, unreliable. It is common
knowledge that the what() string of the exceptions thrown by standard
library implementations is close to completely useless.
> In another thread, Peter Dimov has pointed out that providing a what()
> message that can be used as a key is helpful in internationalizing
You can replace "helpful" by "required". The alternatives, from software
design perspective, are inferior.
> Has anyone run into a comprehensive attack on these and similar exception
> class problems? Is there a better way than each Boost developer just
> hacking together individual exception classes? Could we do better with a
> Boost exception class or idiom?
std::exception, if used correctly, can solve these problems.
One problem with defining a separate exception hierarchy is that sometimes
it's useful to choose std::logic_error, or std::runtime_error, as a base
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk