Boost logo

Boost :

Subject: Re: [boost] [contract] oldof failure not in N1962?
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-07-19 14:14:25


On Tue, Jul 19, 2011 at 10:48 AM, Dave Abrahams <dave_at_[hidden]> wrote:
>
> on Mon Jul 18 2011, Vicente Botet <vicente.botet-AT-wanadoo.fr> wrote:
>
>>
>> Hi Lorenzo,
>>
>> I don't remember what N1962 says, but I would force that preconditions and
>> post conditions evaluation shall not throw. If an exception is throw during
>> precondition evaluation, post-condition preparation or evaluation I would
>> say the program should terminate, as the program can not state if the
>> conditions are satisfied or not.
>
> That doesn't make any sense to me.  If you run out of memory while
> evaluating a precondition, it means you can't evaluate the precondition,
> not that the program can't recover.
>
> My guidelines are:
>
> - Use exceptions for recoverable conditions.
>
> - Do not use exceptions for non-recoverable conditions
>
> - Failure to satisfy a precondition is a program bug
>
> - Program bugs are non-recoverable
>
> - Anticipated failure to satisfy a postcondition (e.g. I can't get
>  enough memory to do my job) is a recoverable condition

Yes agreed but I'm sorry I managed to confuse everyone with this post
because I meant to ask something different...

Part of the issue might be that when someone mentions exceptions and
Contract Programming together the discussions if a contract failure
shall terminate the program or throw an exception starts almost
automatically... However, my question was NOT about throwing or
terminating in case of a contract failure. In case of a contract
failure, Boost.Contract calls the contract broken handlers which by
default call std::terminate (unless the user redefines the handlers to
do something else-- which could be to throw an exception, or print a
message, or play a sound, or anything the user wants to do). This is
exactly what N1962 specifies. In addition, the contract broken
handlers (and therefore std::terminate by default) are called if an
exception is thrown while checking a contract assertion.

My question instead, is: What shall I do if I fail to copy an oldof
value? Specifically, what shall I do if an oldof copy throws an
exception? This is not specified by N1962 (as far as I can see). I
decided that if I fail to copy and olfof value then I call the
postcondition_broken handler but only after executing the body (even
if oldof values are internally copied before the body is executed). I
am personally satisfied with this approach (letting the exception fly
out for the function would also be kind of OK but I didn't like it as
much because the caller might have no sense of the "new" exception
that is thrown only when contract code, the oldof, is evaluated and
never by the body itself).

For example, for std::vector::push_back:

    CONTRACT_FUNCTION_TPL(
    public void (push_back) ( (T const&) vlaue )
        postcondition(
            auto old_size = CONTRACT_OLDOF size(), // (1)
            size() == old_size + 1 // (2)
        )
    ) ;

If (2) evaluates to false, the postcondition_broken() function is
called. If an exception is thrown while checking (2),
postcondition_broken() is also called. postcondition_broken() will
just call std::terminate() however the user can redefined it assigning
a different function to the postcondition_broken() handler using
set_postcondition_broken(). All of this is in accordance with N1962
(as far as I understand it).

Now, my question is: What shall I do if an exception if thrown while
evaluating (1)? I have decided to still call postcondition_broken().

In either cases of (1) or (2) failing, postcondition_broken() is
always called after the body is executed. However, (1) is internally
evaluated before the body while (2) is evaluated after the body.

Thanks to all for your inputs and I hope I was able to clarify my question...

--Lorenzo


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