
Pavel Vozenilek wrote:
"Emil Dotchevski" wrote:
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