[MMXX-dev] Revise the exception management model?
Status: Pre-Alpha
Brought to you by:
ljr
|
From: Luca R. <lj...@us...> - 2000-06-01 20:59:49
|
In preparation for 1.0d6, which should hopefully be the last pre-alpha version, there are a couple issues I'd like to get feedback on. The first relates to the exception management model. An initial (unreleased) design did not use the x_exception encapsulator mechanism, but rather called for throwing pointers to MMXXException's and descendants. After having been with the x_exception mechanism for a while, I'm beginning to reconsider whether the pointer-throwing arrangement was not in fact a better solution. Here's a short summary of the pros and cons of each method: Throwing pointers: ----------------- - Simplifies catching: you can catch any MMXXException subclass with precision, and default out to further bases, up to MMXXException* itself. - The biggest drawback is that each and every catch block has responsibility for VirtualDelete()'ing the caught exception. - The second drawback is that users must be careful not to throw or catch the actual types rather than the pointers. - The third drawback is that conceivably, there exist really poor compilers that can't throw/catch pointers well. In particular, if I throw dynamic_cast<BASE*>(p), the compiler needs to be able to catch (DERIVED *p) where BASE and DERIVED are of course polymorphic (though this issue could be worked around if throwing DERIVED*'s works well on all platforms.) Throwing x_exception pointer encapsulators: ------------------------------------------ - Simplifies deleting, as the encapsulator automatically VirtualDelete()'s the exception upon exiting the catch block, unless it was release()'d. Also simplifies type-checking as x_exception will only encapsulate MMXXException's and subclasses. - The biggest drawback is that catch blocks are nasty. Since there's no way for a catch clause to differentiate among the particular encapsulated MMXXException subclass, all the MMXX exceptions must be caught in one catch block, their actual type switch()'ed upon, and any undesired ones re-thrown. - The second drawback is that this arrangement is probably more confusing. - The third drawback is that there are copy-construction issues that could manifest themselves with certain compilers and/or user patterns, as noted in the docs. Some other points: ----------------- - Interestingly enough, since exceptions are always marshalled at boundaries by way of MMXXMetaobject's, it's possible to make both mechanisms available and let the user pick, while maintaining full compatibility with modules written with the other mechanism. However, this just might add more confusion than it adds flexibility. - There are actually third and fourth options, both of which involve deriving from x_exception (perhaps by way of some additional header macros.) In the third option, there's a template class x_texception that derives from x_exception and is parametrized on the class being thrown. That way you can either catch the exact exception in question, or all MMXX exceptions, but you can't catch on a derivation basis, since catch clauses will not use implicit type conversions. The fourth option is to have non-template, yet parametrized xe_* encapsulators whose derivation hierarchy mimics that of the actual classes, e.g. xe_MMXXException encapsulates an MMXXException pointer, xe_MyDerivedException derives from it to encapsulate MyDerivedException pointers and so on. The main drawback with this is that it adds yet another auto-generated class, and is probably no less confusing than any of the other arrangements. What do you think? Luca |