
On Wed, May 13, 2009 at 11:26 PM, Adam Badura <abadura@o2.pl> wrote:
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?
If you don't insist on the diagnostic message to be user-friendly, just use current_exception_diagnostic_information:
That is not the same. With current_exception_diagnostic_information I sure can achieve the desired result but in an ugly way which likely is also inefficient and prone for failure due to another exception being thrown (for example in low memory conditions). In cases I want to wrap just caught exception I inject it into exception object to be thrown as exception_ptr data. This is something like: typedef boost::error_info< struct Tag, boost::exception_ptr > wrapped_exception_ptr; void load_data() { try { // Do internal staff. // Caller should not be interested in the details. } catch ( const implementation_specific_type& ) { BOOST_THROW_EXCEPTION( load_data_error() // << inject some additional information as required << wrapped_exception_ptr( boost::current_exception() ) ); } } and then latter try { load_data() } catch ( const load_data_error& e ) { std::clog << boost::diagnostic_information( e ); } catch ( ... ) { std::cerr << "Fatal error. Abort." << std::endl; std::abort(); } Note that this way, as I already described, while calling load_data I do not have to bother what is its current implementation and what it might throw. I know that it throws load_data_error if it fails but I can continue (however without the data) or anything else in case of catastrophic errors. (The examples might be more complicated.) However I do not loose even thinnest bit of information. Or rather I wouldn't if boost::diagnostic_information was able to deal with error_info of exception_ptr. But it does not. I could simulate this by asking the exception object for wrapped_exception_ptr and if it returns one then rethrowing that exception catching it and doing current_exception_diagnostic_information for it. And likely doing it in loop since the chain of exceptions may be longer. Adding function like std::string to_string( const wrapped_exception_data& _e ) { try { boost::rethrow_exception( _e.value() ); } catch ( ... ) { return boost::current_exception_diagnostic_information(); } return "to_string exiting unexpectedly"; } helps a bit since boost::diagnostic_information will handle now wrapped_exception_data and the "loop" for chained exceptions is achieved automatically. However it still requires to throw and catch. And this does not seem right. (Also note the return value at the end. I had to add it while compiling on MS VS 2005 since is warned about not every control path returning a value. Why rethrow_exception (and likely other similar functions as well) is not marked as no-return? In case of MS VS 2005 it is done quite easy... But if I am recalling well someone already asked for it.) If I am not mistaken it shouldn't be hard to allow boost::diagnostic_information act on exception_ptr like on ordinary exception. And yes. I know you are against chaining exceptions. However I showed some use cases and you haven't showed any other solution to those (which does not mean that non exists). Also note that simply copying data from one exception to the other will not do as it might override some data (like the basic ones: file name, line number and function name). Adam Badura