Boost logo

Boost :

Subject: Re: [boost] [contract] relaxing preconditions in subcontracting
From: lcaminiti (lorcaminiti_at_[hidden])
Date: 2012-06-12 09:05:30


Andrzej Krzemienski wrote
>
> I am trying to understand how the feature of relaxing preconditions in
> overridden functions work or should work. Given the situation, where I
> call
> an overridden function via base class reference:
>
> *struct Base
> {
> virtual void fun(bool b) = 0 precondition{ b == true };
> };
>
> struct Deriv : Base
> {
> void fun(bool b) override precondition{ true };
> };
>
> void test( Base & b )
> {
> b.fun(false); **// broken contract or not?**
> }*
>
> Should this be treated as a broken contract or not? My reading of the
> documentation says that contract is not broken (because the
>

If b.fun(false) is valid or not depends by the actual object referenced by b
(?!). For example:

Deriv d;
test(d);

This passes because the subcontracted precondition of d.func(false) is
`true or (false == true)` which is true. However if:

struct Deriv2 : Base
{
  void fun(bool b) override precondition{ false };
};

Deriv2 d2;
test(d2);

This fails because the subcontracted precondition of d2.func(false) is
`false or (false == true)` which is false.

This is how the library is implemented, however, is this a correct
implementation of the substitution principle
http://en.wikipedia.org/wiki/Liskov_substitution_principle? Or should this

void test( Base & b )
{
  b.fun(false); **// broken contract or not?**
}*

always and just check the precondition of base::fun?

I'm honestly not sure, I need to think about it more and also check what
Eiffel does... I'll take that as a homework.

> "logic-or<http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_0_4_0/doc/html/contract__/contract_programming_overview.html#logic_or_anchor>"
> logic applies), but I feel that whoever implemented function *test *made a
> mistake: he cannot assume what type will be implementing "interface"
> *Base*,
> so he cannot rely on the precondition being relaxed (even if he gets away
> with it this time).
>

If you find this confusing, welcome to the club ;) N1962 prohibits
overriding preconditions "even if subcontracting is theoretically sound and
based on substitution principle, precondition can only be defined by base
classes...". I find overriding preconditions also confusing.

My library allows you to prohibit subcontracted preconditions like N1962
specifies by defining the configuration macro
CONTRACT_CONFIG_DO_NOT_SUBCONTRACT_PRECONDITIONS (however, in case of
multiple inheritance preconditions of all base classes are still checked in
logic-or with respect to each other, N1962 does not discuss this case
explicitly...).

I tried to document this in the Advanced Topics section:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_0_4_0/doc/html/contract__/advanced_topics.html#contract__.advanced_topics.subcontracting_preconditions

At the end, my library should:
1) Implement what defined by the substitution principle (and implemented by
Eiffel).
2) But provide a configuration macro to avoid all this confusion by
generating a compiler error if you try to subcontract a precondition.

Thanks,
--Lorenzo

--
View this message in context: http://boost.2283326.n4.nabble.com/contract-relaxing-preconditions-in-subcontracting-tp4631177p4631178.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

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