
<snip> No, not my point. It's about increasing the expressiveness of client code: It provides means for a user to express: "I'm going to throw a bunch of exceptions (starting) with common attributes. Please give me a brief way to create them, so error reporting doesn't obscure my code."
It also allows to easily port "traditional" exception classes to boost::exception.
Further it would allow to allocate the attributes of a custom_exception in one shot.
Yes, I think I understand your point, but...
So, I'd write that function like this:
void read_file( char const * filename ) { try { something_unrelated(); .... if( file_failure ) throw file_error(); } catch( boost::exception & x ) { x << error_info<tag_filename>(filename); throw; } }
How would your custom_exception idea fit in this framework?
So now you're bringing up a different use case.
... I'm bringing up the different use case because -- at least in my experience -- it is very common when using boost::exception; I'm trying to convince the audience that the effort to bundle multiple pieces of data together perhaps isn't as beneficial as one hopes, because a lot of times all you have is a single piece of data that is relevant to a failure. Please bear with me for one more example :) shared_ptr<FILE> open_file( char const * name, char const * mode ) { if( FILE * f=fopen(name,mode) ) return shared_ptr<FILE>(f,fclose); throw file_open_error() << error_info<tag_file_name>(name) << error_info<tag_open_mode>(mode) << error_info<tag_errno>(errno); } void read_file( shared_ptr<FILE> const & f, std::vector<char> & buf ) { .... size_t s=file_size(f); if( s>max_size ) throw file_too_big_error() << error_info<tag_file_size>(s) << error_info<tag_max_file_size>(max_size); .... } void parse_data( char const * data, size_t s ) { .... if( parse error ) throw parse_data_error() << error_info<tag_parse_error_code>(15) << error_info<tag_parse_error_offset>(offset) << erorr_info<tag_parse_buffer>(std::string(data,s)); .... } void parse_file( char const * name ) { shared_ptr<FILE> f=open_file(name,"rt"); try { std::vector<char> buf; read_file(f,buf); parse_data(&buf[0],buf.size()); } catch( boost::exception & x ) { x << error_info<tag_filename>(name); throw; } } Though this code is far from being complete, parse_file can emit the following exceptions already: file_open_error file_too_big_error parse_data_error If we make this example complete, the list will be longer still. In my mind, it makes no sense to bundle tag_file_name, tag_open_mode, and tag_error together (which, if I understand is what you were thinking), because they appear together in only one exception: file_open_error. On the other hand, tag_file_name is relevant to any failure occuring within parse_file. We shouldn't worry about what else might be relevant, or how to bundle it -- we just stuff in the exception whatever is known to us. In particular, note that parse_data doesn't deal with files at all; it can't possibly "bundle" a file name in the parse_data_error exception, but at the same time if the data came from a file, we don't ever want that particular parse_data_error to reach a catch without a file name. Emil Dotchevski