Boost logo

Boost :

From: Ed Brey (brey_at_[hidden])
Date: 1999-07-09 08:48:36


Email seemed somewhat boring, until Dave Abrahams wrote:
>
>> destructor can and should have an empty throw specification
>
>Why "should"?

Good point. I was thinking that the destructor would know that it
won't throw, but this may not be the case, since it may have to call
undecorated functions.

>Even if compilers "get up to par", the exception-specification on the
>destructor will occur the same overhead unless the compiler can prove that
>nothing it calls will throw an exception. The only way that can happen is if
>all functions called in the destructor also have an empty
>exception-specification, and so on, and so on... Since lots of code is being
>written today which doesn't throw and also doesn't use
>exception-specifications, this is unlikely to pay off.

I hadn't considered the destructor calling undecorated functions.
Most of my destructors do simple cleanup and don't call any functions,
but there certainly do exist destructors that need to call old,
undecorated functions. I agree that this makes putting a throw
specification on the destructor a bad idea, since the compiler would
then need to wrap the destructor in an implicit try block.

>To get the gains you anticipate, you have to live in a world where all
>compilers are perfect and where everyone writes empty
>exception-specifications wherever possible. But exception-specifications
>have a downside: not everyone wants the termination semantics that they
>imply, and they cause big problems for program evolution and maintenance. In
>particular, you lose the benefits of the separation of interface from
>implementation when an exception-specification is placed on a
>non-destructor.

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.

>> I think that we should document the interface showing reset and
>> ~scoped_ptr as having empty throw specifications, document that the
>> pointee destructor should have an empty throw specification, and then
>> actually implement the empty throw specifications with a temporary macro
>> hack to disable the throw specifications in scoped_ptr and the pointee
>> for compilers that don't handle it efficiently.
>
>I will never agree with you that this is preferable.

I'm not a big fan of statements of such inflexibility, since they
contribute little and can shunt innovation, but since you're right,
I guess I really can't complain. <g>

To help future library users from reraising this issue, perhaps the
rationale on the bottom of
http://www.boost.org/libs/smart_ptr/smart_ptr.htm should be augmented
to mention that the exception specification was omitted because the
smart_ptr classes are designed to work with pointees that have
undecorated destuctors. The current explanation: "Because there is no
way to directly express this prohibition in C++, compilers would be
forced to generated unneeded try/catch blocks if throw() was coded."
makes it sound to me like if there was a way that a smart_ptr could
cause a compile error if the pointee's destructor didn't have
throw(), Boost would have done that.

Also, the sentence "For functions which can throw std::bad_alloc, empty
throw specifiers are not supplied." is confusing. Of course empty
throw specifiers woundn't be supplied. 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. 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.

The question that remains is what to do until the compilers get up to
speed. I like the purity of coding what it should be and using macros
or other hacks in the iterum. This has the advantage of allowing the
people with good compilers to make use of the exception specifications,
whereas losers like me with VC can keep it in "make it work" mode for
a while.

------------------------------------------------------------------------

eGroups.com home: http://www.egroups.com/group/boost
http://www.egroups.com - Simplifying group communications


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