
On Tue, Jul 19, 2011 at 10:48 AM, Dave Abrahams <dave@boostpro.com> 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