
I'm not keen on the use of operator<< to add the data to the exceptions.
I do share your concern, but consider that whatever we use for boost exception should support easy composition, because it needs to work when used in a throw expression directly: throw my_error() << error_info<tag_errno>(errno) << error_info<tag_name>(name); Instead of << we could use .add: throw my_error(). add(error_info<tag_errno>(errno)). add(error_info<tag_name>(name)); This isn't bad, but in my opinion the << syntax is better despite my strong dislike for operator overloading.
<snip> catch (some_exception& E) { E << " while frobinacting at warp level " << warp_level; throw; }
Of course this isn't going to work.
Right, it's not going to compile.
Is "exception" the best choice of name for this library? The name boost::exception might give the impression that it's the base class for all Boost exceptions, which is not the case;
In my ideal world, the functionality of boost::exception would be implemented directly by std::exception ;) That said, there is an easy way to make boost::exception the base of all exception emitted by boost: #ifdef BOOST_NO_EXCEPTIONS namespace boost { void throw_exception(std::exception const & e); // user defined } #else #include <boost/exception.hpp> namespace boost { template<class E> void throw_exception(E const & e) { throw enable_error_info(e); //see documentation } } #endif (I'm now thinking we need to add some trickery to enable_error_info, so it does not inject boost::exception as a base if it is a base already.) This adds very little overhead to all exceptions: an empty shared_ptr, which does not allocate any memory. The benefit is that now user code can catch any boost exception as a boost::exception, and add application-specific error information to exceptions coming from boost libraries: try { ---use boost--- } catch( boost::exception & x ) { x << error_info<my_info>(.....); throw; }
Also, there's the possibility that someone might propose some other exception-related library, orthogonal to this one, in the future. How about "tagged_exception"?
I think there is a lot of value to enabling all exceptions to carry arbitrary failure-related information. The main motivation for Boost Exception is that a library that throws an exception can not possibly anticipate everything that is relevant to that type of failure in a particular client application. I think that even if a particular library has no info to add to an exception, it should throw exceptions that derive from Boost Exception, even if it's just to enable information to be added later on. If you agree with the above, I think you'd agree that boost::exception is the appropriate name to use. That said, I am very much interested all negative feedback. Do you see any reasons why you wouldn't want to use Boost Exception as a base for all of your exceptions? Do you think the current design of Boost Exception can be improved so it better serves its intended design goal as universal base class that can transport arbitrary failure-related data to the catch site?
You might like to say something about the overhead that is added, i.e. that there is a std::list<something> in each exception (or whatever). (Remember that there are still plenty of people who dislike exceptions because of the perceived overhead that they involve.)
In this particular library we shouldn't be concerned with people who don't like exceptions because of the exception handling overhead itself. As for the additional overhead of Boost Exception, the price you pay if you don't add any info to it is an empty shared_ptr. If you do add info, then more memory is allocated -- however notice that all of that memory is allocated only when throwing exception, and that it is freed when the exception is handled. I can't imagine a use case when that would cause any issues.
I think you do say something about the exception guarantee, but it might be useful to add a more explicit section near the start describing the exception guarantee and also whether any dynamic memory allocation is involved; what happens if the exception that was thrown was "out of memory"?
That's in the FAQ already. :) Emil Dotchevski