[contract] non-public subcontracting (N1962)

Hello all (and N1962 authors especially), How should subcontracting work for non-public base classes? I have listed a few examples below. Assume contracts were written for all these example classes (invariants) and their functions (pre/post conditions). My questions are: A) `c::p()` should subcontract; but what about any of the other member functions of `c`, should any of them subcontract also? B) Am I missing any other combination of member/inheritance access level significant for deciding when to subcontract? class bp { public: virtual void p(void) { std::cout << "bp called" << std::endl; } }; class bf { protected: virtual void f(void) { std::cout << "bg called" << std::endl; } }; class bg { public: virtual void g(void) { std::cout << "bg called" << std::endl; } }; class bh { public: virtual void h(void) { std::cout << "bh called" << std::endl; } }; class c: public bp, public bf, protected bg, private bh { public: // This should subcontract. virtual void p(void) { bp::p(); } // Should any of the following subcontract also? virtual void f(void) { bf::f(); } virtual void g(void) { bg::g(); } virtual void h(void) { bh::h(); } // Am I missing any other relevant combination? }; (I do not think multiple inheritance is relevant for my questions. I am using multiple inheritance in this example just so to have only one derived class `c` which exercises all the use cases.) My notes and questions: 1) All member functions of `c` are public so they will check their pre/post conditions as in `c` and `c` class invariants. 2) But shall any `c` member functions also check their base class invariants and/or base function pre/post conditions? 3) `c::p()` should subcontract `bp::p` pre/post and `bp` inv because it is a public function publicly inheriting from a base public function. ** 4) Maybe `c::f()` should subcontract `bf::f()` pre/post but not `bf` invariant... (because `bf::f` is protected thus it does not have to check `bf` invariant). ** ** 5) Should `c::g()` and `c::h()` subcontract given that their inheritance is not public? ** Thank you very much. -- Lorenzo

Hello everyone, Allow me to reiterate my question: On Sun, May 30, 2010 at 8:42 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
How should subcontracting work for non-public base classes? (See details in my previous email below.)
From Cline and Lea, "The Behavior of C++ Classes", 1990 -- A++: <<< 3.3 Inheritance C++ supports both public and private subclasses. Private subclasses are used either for partial code reuse or to express a has-a relationship. With private derivation, no mechanism is provided for automatic inheritance either by C++ (inheritance of the public interface) or by A++ (inheritance of behavioral constraints). Public derivation express the is-a or subtype relation: if VStack is
1) I have looked at N1962 (and its previous revisions) but I could not see how the proposal addresses non-public inheritance. I might be missing something (given that the N1962 is rather detailed)... 2) What Eiffel does in this case does not help me much because there is not really something like protected inheritance in Eiffel... 3) I looked at an old Contract Programming proposal for C++ called "A++". This proposal addresses this issue as quoted below but this is a very old proposal from 1990 so I cannot consider it the "state of the art". BTW, I am asking because I need to decide how to implement subcontracting for protected and private inheritance in Boost.Contract. One option could be (essentially following A++): a) Preconditions, postconditions, and invariants are all subcontracted for public inheritance. b) Only preconditions and postconditions (but no invariants) are subcontracted for protected inheritance. c) Nothing is subcontracted for private inheritance. This should still satisfy Liskov substitution principle. What do you think? publically derived from Stack, a VStack is-a Stack. The implication, lacking currently in C++, is that a VStack should behave like a Stack. This is accomplished in A++ by providing VStack with all the behavioral specications of Stack. Since the two types may use inherited protected members dierently, the legal and coherent class-wide specications are not automatically inherited.
On Sun, May 30, 2010 at 8:42 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all (and N1962 authors especially),
How should subcontracting work for non-public base classes?
I have listed a few examples below. Assume contracts were written for all these example classes (invariants) and their functions (pre/post conditions).
My questions are: A) `c::p()` should subcontract; but what about any of the other member functions of `c`, should any of them subcontract also? B) Am I missing any other combination of member/inheritance access level significant for deciding when to subcontract?
class bp { public: virtual void p(void) { std::cout << "bp called" << std::endl; } };
class bf { protected: virtual void f(void) { std::cout << "bg called" << std::endl; } };
class bg { public: virtual void g(void) { std::cout << "bg called" << std::endl; } };
class bh { public: virtual void h(void) { std::cout << "bh called" << std::endl; } };
class c: public bp, public bf, protected bg, private bh { public: // This should subcontract. virtual void p(void) { bp::p(); } // Should any of the following subcontract also? virtual void f(void) { bf::f(); } virtual void g(void) { bg::g(); } virtual void h(void) { bh::h(); } // Am I missing any other relevant combination? };
(I do not think multiple inheritance is relevant for my questions. I am using multiple inheritance in this example just so to have only one derived class `c` which exercises all the use cases.)
My notes and questions: 1) All member functions of `c` are public so they will check their pre/post conditions as in `c` and `c` class invariants. 2) But shall any `c` member functions also check their base class invariants and/or base function pre/post conditions? 3) `c::p()` should subcontract `bp::p` pre/post and `bp` inv because it is a public function publicly inheriting from a base public function. ** 4) Maybe `c::f()` should subcontract `bf::f()` pre/post but not `bf` invariant... (because `bf::f` is protected thus it does not have to check `bf` invariant). ** ** 5) Should `c::g()` and `c::h()` subcontract given that their inheritance is not public? **
Thank you very much.
-- Lorenzo
-- Lorenzo

On Thu, Jun 3, 2010 at 11:31 PM, Thorsten Ottosen <nesotto@cs.aau.dk> wrote:
Lorenzo Caminiti skrev:
Hello everyone,
Allow me to reiterate my question:
I'm too busy to answer right now, so please have a little patience. I'll be back monday.
No problem. In fact, this can wait 2-3 weeks with *no* implications on my work on Boost.Contract. Looking forward to discuss whenever you have time. Thanks a lot. -- Lorenzo

Lorenzo Caminiti skrev:
Hello everyone,
Allow me to reiterate my question:
On Sun, May 30, 2010 at 8:42 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
How should subcontracting work for non-public base classes? (See details in my previous email below.)
1) I have looked at N1962 (and its previous revisions) but I could not see how the proposal addresses non-public inheritance. I might be missing something (given that the N1962 is rather detailed)...
Well, since it has no special case for this, the same rules apply for all types of virtual functions.
2) What Eiffel does in this case does not help me much because there is not really something like protected inheritance in Eiffel...
You can override a private virtual function, so why should the rules be special for them?
3) I looked at an old Contract Programming proposal for C++ called "A++". This proposal addresses this issue as quoted below but this is a very old proposal from 1990 so I cannot consider it the "state of the art".
I had not seen this before. Thanks.
BTW, I am asking because I need to decide how to implement subcontracting for protected and private inheritance in Boost.Contract. One option could be (essentially following A++): a) Preconditions, postconditions, and invariants are all subcontracted for public inheritance. b) Only preconditions and postconditions (but no invariants) are subcontracted for protected inheritance. c) Nothing is subcontracted for private inheritance. This should still satisfy Liskov substitution principle.
I guess you can do whatever is the easiest. I'm not up to date with the rules, but is it not so that I can override a priviate virtual function of a private base class? If so, I see no reason to make special rules forbidding subcontracting although it is somewhat unclear what the point with a such a piece of code would be. -Thorsten

Sorry for the late reply but I just realized that my original reply of Jun 9 bounced back... On Tue, Jun 8, 2010 at 4:28 PM, Thorsten Ottosen <nesotto@cs.aau.dk> wrote:
Lorenzo Caminiti skrev:
Hello everyone,
Allow me to reiterate my question:
On Sun, May 30, 2010 at 8:42 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
How should subcontracting work for non-public base classes?
(See details in my previous email below.)
1) I have looked at N1962 (and its previous revisions) but I could not see how the proposal addresses non-public inheritance. I might be missing something (given that the N1962 is rather detailed)...
Well, since it has no special case for this, the same rules apply for all types of virtual functions.
Does "the same rules" mean that, regardless of the inheritance access levels of the base classes: 1) Preconditions are checked in OR with the ones of all base functions. 2) Postconditions are checked in AND with the ones of all base functions. 3) Class invariants are checked in AND but only with base class invariants for of public base functions. I want to make sure I understand especially 3) clearly in the context of deep inheritance level (not multiple inheritance). Assume contracts were written for all these classes and member functions: class a { // Don't check a:: invariants. protected: virtual void f(void) {} }; class b: public a { // Check b:: invariants (but not a:: invariants). public: virtual void f(void) {} }; class c: protected b { // Check b:: invariants (but not c:: or a:: invariants). protected: virtual void f(void) {} }; class d: protected c { // Check d:: and b:: invariants (but not c:: or a:: invariants). public: virtual void f(void) {} }; A call to d::f() will end up checking d:: and b:: class invariants but not c:: or a:: class invariants -- correct?
2) What Eiffel does in this case does not help me much because there is not really something like protected inheritance in Eiffel...
You can override a private virtual function, so why should the rules be special for them?
Yes, you can override a private virtual function and do so even if the base class is private (I have written a simple example to double check that). Therefore, "no special rule" is a reasonable option.
3) I looked at an old Contract Programming proposal for C++ called "A++". This proposal addresses this issue as quoted below but this is a very old proposal from 1990 so I cannot consider it the "state of the art".
I had not seen this before. Thanks.
This was cited in "Design and Evolution of C++". If you are interested, you can find A++ papers at: http://gee.cs.oswego.edu/dl/papers/A++-sooppa.ps (the page order is reversed...) http://gee.cs.oswego.edu/dl/papers/A++-C++AtWork.ps
BTW, I am asking because I need to decide how to implement subcontracting for protected and private inheritance in Boost.Contract. One option could be (essentially following A++): a) Preconditions, postconditions, and invariants are all subcontracted for public inheritance. b) Only preconditions and postconditions (but no invariants) are subcontracted for protected inheritance. c) Nothing is subcontracted for private inheritance. This should still satisfy Liskov substitution principle.
I guess you can do whatever is the easiest. I'm not up to date with the rules, but is it not so that I can override a priviate virtual function of a private base class? If so, I see no reason to make special rules forbidding subcontracting although it is somewhat unclear what the point with a such a piece of code would be.
I think, the subcontracting rules of A++ make sense but they are a bit more complex for users to understand than N1962 simpler rule "there is no special rule". Furthermore, I have never experienced any real benefit/need for implementing something like A++ subcontracting rules. Therefore, I am happy to implement Boost.Contract as specified by N1962 with "no special subcontracting rule based on the base class inheritance access level". (However, I might have more observations on the topic once I start implementing this.) -- Lorenzo
participants (2)
-
Lorenzo Caminiti
-
Thorsten Ottosen