From: Ed Brey (brey_at_[hidden])
Date: 1999-07-12 08:17:27
Email seemed somewhat boring, until Dave Abrahams wrote:
>> I hadn't considered the destructor calling undecorated functions.
>> Most of my destructors do simple cleanup and don't call any functions...
>Except sub- and base-object destructors, implicitly.
Right. I didn't mention those, since I tend to have control over them
and can put empty throws on them, unless they too call legacy functions
such as the Windows API, which where I find the majority of my problems.
>> I don't understand your reasoning for why exception specifications
>> deteriorates the separation of interface from implementation. The
>> exception specification is part of the interface and just one more
>> constraint that the implementation must adhere to. Like all
>> constrains imposed by an interface, if the exception specification
>> is too inflexible, this will cause problems for the implementation.
>empty exception-specifications on destructors may be an exception to the
>rule, but in general an exception-specification may restrict
>interface-preserving changes you can make to the implementation of a
>function during the normal course of maintenance. Since there is essentially
>no compile-time enforcement of exception-specifications, it can be very
>difficult to be sure that you haven't made a change which violates an
Maybe a good compromise is to include std::bad_exception in the throw
specifications and require that unexpected() throws. This allows an
interface to specify a finite list of exceptions that can be thrown,
rather than leaving it wide open, but keeps the program from terminating
in case a function within the interface (intentionally or unintentionally)
throws an excpetion outside of what is listed in its contract.
>> The issue is why isn't
>> throw(std::bad_alloc) specified. I believe all the functions that throw
>> bad_alloc also contain a delete of the user's type. According to the
>> discussion in this thread, this is a good reason for not having a throw
>> specification. However, I'd say that the shared_ptr and shared_array
>> constructors are exceptions (NPI) since they do their deletes within
>> a catch block, and so an exception from the pointee destructor will call
>> terminate anyway.
>Incorrect. An exception thrown from within a catch block works (almost) just
>except that a different exception object is thrown.
Sorry, you're right. I had looked into the spec on that issue and read
that terminate is called "when the destruction of an object during stack
unwinding (15.2) exits using an exception". I mistakenly confused
being in the catch block for stack unwinding.
>> A compiler can (or will someday be able to) realize
>> that the constructor can't throw anything besides std::bad_alloc and
>> so no additional wrapping is necessary.
>And in the mean time you will pay for the extra data tables, at best.
>Where's the advantage in using the exception-specification?
That's a key question, which I am not yet ready to answer. It would
seem that the answer to that question is the same as the answer to
"Why are exception specifications in C++ in the first place?"
My best answer is that they allow the programmer to use the class
knowing he must only code to handle certain exceptions.
Another plus, as has already been brought up in this thread regards
debugging. You can put an assert(false) in unexpected and trap
unexpected exceptions closer to the source.
Are these benefits (and other's I can't think of) worth the cost
of the implicit try block today. I would guess not, but in the
future if try blocks become free (I would appreciate more details
on that subject), then we can freely reap the benefits.
eGroups.com home: http://www.egroups.com/group/boost
http://www.egroups.com - Simplifying group communications
Boost list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk