Boost logo

Boost :

From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2006-08-08 18:28:54


Pavel Vozenilek wrote:
> "Emil Dotchevski" wrote:
>
>>>> http://article.gmane.org/gmane.comp.lib.boost.devel/146322
>>
>> Could you provide an example of using this functionality at the top
>> level of
>> an application?
>
> int main()
> {
> try {
> .... run application
> } catch(boost::exception& e) {
> e.dump_everything(); // what happened?
> }
> }

Yes, but what does dump_everything() look like?

The reason why this is important is that I can't imagine dump_everything
being able to format a proper user message. The best it can do is dump stuff
in a debug log, for example. Which begs the question, how do you format a
proper message for the user? I think that the only way to do this is for the
code that formats the message to *know*, for each class of exceptions, what
info could be available. You can't parameterize this with a "visitor"
interface. Or can you? That was my intention when I asked you for an
example: what's in dump_everything?

>>> There should be also ability to support
>>> visitation of exception objects.
>>> Imagine situation:
>>>
>>> try {
>>> ....
>>> } catch (boost::exception& e) {
>>> e << ....;
>>>
>>> // now some exceptions could be handled
>>> // and some need to be passed up
>>> ????
>>
>> I am not sure I understand what you mean by typeswitch.
>> Can you illustrate your point with more code?
>
> typeswitch:
> if (dynamic_cast<This>(e)) .... else
> if (dynamic_cast<That>(e)) ....

What's wrong with

catch( This & )
{
}
catch( That & )
{
}
...

> A visitor solution:
>
> try {
> ...
> } catch (boost::exception& e) {
> e << ...
>
> my_visitor m;
> m.process(e);
> }
>
> Now the visitor will have a typelist
> of exceptions it does handle and will
> internally generate a chain
> of dynamic_casts to select the most
> appropriate visit() function to be called.

You are trying to use value semantics with exception handling. Essentially,
I don't see much of a difference between --

class foo: public exception { };
class bar: public exception { };

{
    ....
    throw foo();
}

...
catch( exception & e )
{
    if( dynamic_cast<foo *>(&e) )
        ....;
    if( dynamic_cast<bar *>(&e) )
        ....;
}

-- and --

int const foo = 1;
int const bar = 2;

{
    ....
    throw foo;
}

...
catch( int e )
{
    if( foo==e )
        ....;
    if( bar==e )
        ....;
}

Even if you use a map of some sort hidden behind a "visitor" interface, you
are replacing the "catch-by-type" semantics of C++ with
"catch-everything-and-examine-its-value" semantics. I don't think this is a
good idea. I think we should stick to throwing unnamed temporaries, and
catching by reference, based on the *type* of the exception object, not its
*value*.

> My partial inspiration is chapter Visitor from
> Alexandrescu's Modern C++ Design
> but it is (IMHO) possible to avoid
> any modifications of the visited
> classes (the exceptions) for the cost
> of more processing on visitor side.
[snip]

I understand what you mean, but I still think that this is a departure from
the exception handling semantics intended by the C++ designers. This doesn't
mean that it doesn't make sense, just pointing that out.

My personal opinion is that a list of ordered catch statements is the
simplest way to get what you need. And it is directly supported by C++.

--Emil


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