Proposed Structure for Library Exceptions X3J16/93-0110 WG21/N0317 29 July 1993 P.J. Plauger Here are a number of suggestions for improving the coherence of exception handling in the Standard C++ library. I haven't attempted to make much of a hierarchy of exceptions, since I understand that at least one other proposal addresses that issue. >> Have constructors for C strings and class string The version of class exception I put in the library draft (one of several kicking around to choose from) is constructed with three NTMBSs (null-terminated multibyte strings, beginning and ending in the initial shift state, with static lifetimes or lifetimes at least as long as the exception object): class xmsg { public: xmsg(const char *what, const char *where, const char *why); ... The LWG discussed having a derived subtree of this class accept higher-level text constructs, such as our library class string. (You can't always do so, otherwise xalloc can be hard to construct when you're out of heap.) I propose instead that we simply add a second constructor: xmsg(string& what, string& where, string& why); Presumably, the library uses the simpler form where it must (as with xalloc) or where it can choose to do so. The library and users can use the nicer second form whenever heap is not in short supply. >> Provide a way to avoid all throws in the library I've received reports from various circles that throwing exceptions must NOT occur in certain systems. (I know that embedded programs often can't afford the current overheads, but this is a more serious matter of contractual necessity.) Thus, I think we need a way to guarantee that the library can be prevented from throwing any exceptions. The current draft has a virtual void raise() that throws the exception for you. (The class reraise changes this to a rethrow.) I envisioned these virtuals as being user suppliable, as with global operator new, for those who want to avoid throws. In the light of several comments from Jerry Schwarz, however, I now propose: o that class xmsg have a non-virtual void raise(). o that the library always raise an exception ex by calling ex.raise(). o that raise() first call the function designated by set_raise_handler(), then call a protected virtual that does the actual throw (or rethrow). The argument to the handler function would be a reference to the exception. Thus, concerned users could register a handler that intercepts all exceptions before they're thrown. The default handler simply returns, so the exception gets thrown. >> Rename Bad_cast as bad_cast, and throw it with raise() Basically, this requests the language folk to go along with library conventions in this area. >> Eliminate most nested exception classes in library classes Right now, we have a mixed bag of exceptions defined in the library. Some are nested classes, some global. Some were nearly the same, but spelled three different ways (outofmemory, out_of_memory, OutOfMemory). Perhaps we can justify ios::failure as a nested exception class, but most of the others fall into two categories: domain errors -- violate preconditions (invalid_argument, out_of_range, etc.) range errors -- violate postconditions (length error, overflow) I suggest that we add to the header exceptions with names like xdomain and xrange to replace these varied special cases. (We may still choose to document ``error reporting'' on a per-class basis, since it makes a handy summary of what can go wrong.) >> Add an assertion macro that raises an exception. Primitive as it is, the assert macro in C has many adherents. I think that C++ should have a version that raises an exception, providing similar information in its where and why strings.