Boost logo

Boost :

Subject: Re: [boost] [boost::exception] operator >>
From: Gaydov Victor (victor.gaydov_at_[hidden])
Date: 2009-04-19 13:10:08


>
> Emil Dotchevski <emildotchevski_at_[hidden]> wrote:
>> > hello! i'm using boost::exception in one project and did small modification
>> > for myself, what do you think about it ?
>> >
>> > i don't want to create a lot of exception classes, because my 'catches' will
>> > use only a few of them anyway. but while exception is throwing, some
>> > functions add different information to it (with operator <<) that is useful
>> > in diagnostic messages.
>> >
>> > so when we decide to extract that information from exception, we need to
>> > study what useful information it has. instead of using if-else it'll be nice
>> > to use inheritance of _errors_ (not exceptions), for example:
>> >
>> > throw our_exception () << error_1 ();
>> > ...
>> > catch (our_exception & e)
>> > {
>> > re-throw e << error_2 ();
>> > }
>> > ...
>> > catch (our_exception & e)
>> > {
>> > shared_ptr <base_of_error_1_and_2> ptr;
>> > while (e >> ptr)
>> > cout << ptr->format_error_message();
>> > }
>>
>
> I understand what you are doing but I don't understand why. Could you
> provide a non-abstract example of a use case that benefits from this
> addition?
No problem. We have to basic exception classes: errors associated with
external files or system calls and internal interpreter errors.
To work properly, program don't need a lot of information about errors,
but we need this information in error messages.
boost::exception gives simple way to collect error context so each
function does not need to worry about errors it catches, but should just
add its context. In result, content of exception depends on it path
throw function and modules.

A few pieces of code (i omit boring parts):

struct silent : virtual exception { inline silent (guid_t e) : exception
(e) {} };
struct critical : virtual exception { inline critical (guid_t e) :
exception (e) {} };
template <typename level> struct system_error : public level { inline
system_error (guid_t e) : exception (e), level (e) {} };

struct info {
virtual void printf (boost::format &) const = 0;
virtual guid_t format (void) const = 0;
virtual ~info () {}
};

// in RL we generate them using boost macros :)
struct module_info_e : public info
{
guid_t format (void) const { return 101; }
void printf (boost::format & dest) const
{
const boost::tuple < string, string > & tuple
= static_cast < const boost::error_info< module_info_e, boost::tuple
<string, string> > *> (this) -> value();
dest % tuple.get<0>() % tuple.get<1>() ;
}
};

typedef boost::error_info < module_info_e, boost::tuple < string, string
> > module_info ;
enum { bad_module };

.......
// in Module::arch_dependent::load
throw system_error <silent> (bad_module);
.....
// in Module::load
catch (silent & e) { throw e << module_info (make_tuple ("1.so", "error
while loading")); }
.....
// in Script::run that can run command that loads module (or not, we
don't know)
catch (silent & e) { throw e << context_info (make_tuple (current_line)); }
.....
// some function that should be stable
catch (exception & e) { print_error (e); }

print_error() is a point where we should discover exception content.
In above example it is like this:

ostringstream message;
for (boost::shared_ptr <info const> base ; e >> base ; )
{
boost::format format (Sys::Instance().Reader <Resources> :: get
<char_t*> (base->format ( ))); // get format string for error
base->printf (format); // fill format string with error info content
message << format << std::endl;
}

If we use exception hierarchy instead of error information hierarchy we
don't have such freedom like this (using virtual functions) because we
can't combine error information so random. So it is main purpose -- to
avoid worrying about what errors we are catching). Also IMHO it is not
too beautiful because a lot of functions shouldn't know anything about
error information, only about exceptions, so they should be separated.

I don't insist on this, just report changes that I need for myself.
I'm sorry i'm too verbose (or sorry if i'm not verbose enough :)


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk