
Dave Abrahams wrote:
on Tue Jul 19 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
I'm sorry I managed to confuse everyone with this post because I meant to ask something different...
My question instead, is: What shall I do if I fail to copy an oldof value?
I don't think I misunderstood your question, although I don't happen to know what "oldof" means here...
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).
As I said, that doesn't make any sense to me, for the reasons I already gave, and because failure to allocate memory in precondition checking does not amount to a broken postcondition.
But in this case the failure is in allocating memory to copy an old value and NOT in checking preconditions. Failing to copy an old value (e.g., for an alloc failure) will indeed not allow to check postconditions because the postconditions use the old value. Therefore, the postconditions should be considered failed because they cannot be checked and postcondition_broken should be called. All of this reasoning does not have anything to do with the preconditions but only with the postconditions. Old-of values are part of (i.e., they are specified and used by) the postconditions (even if they are internally evaluated before the body and after the eventual preconditions). For example (following N1962 proposed syntax): void push_back(T const& value) postcondition { size() == oldof size() + 1; } { vector_.push_back(value); } Will be effectively implemented by something like this (ignoring class invariants for simplicity): void push_back(T const& value) { // eventual preconditions will be checked here bool oldof_failed = false; size_type old_size; try { old_size = size(); // old-of copy } catch(...) { oldof_failed = true; } // the body can be called here (regardless of oldof_failed) because precondition passed vector_.push_back(value); // body try { if(oldof_failed) throw runtime_error("old-of failed"); if(!( size() == old_size + 1 )) throw logic_error("postcondition failed"); } catch(...) { postcondition_broken(); // will call std::terminate (by default) } } Where: void default_handler() { std::terminate(); } typedef void (*broken_handler)(); broken_handler postcondition_broken = &default_handler; void set_postcondition_broken(broken_handler h) { postcondition_handler = h; } You can redefine postcondition_broken to be smart and say "if there is an active exception that indicates the failure was because of an old-of copy then free some memory and signal the caller to retry the push_back call, else call std::terminate".
That said, the function itself might be a nothrow function and turning on contract checking should not change the function's semantics. That would be my only argument against throwing an exception.
--Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/boost-contract-oldof-failure-not-in-N1962... Sent from the Boost - Dev mailing list archive at Nabble.com.