From: Jens Auer on 29 Jun 2010 05:35 I am trying to implement some tools to ease design by contract. To check invariants automatically at the beginning and end of member functions, I intend to use a helper object which does this in RAII- fashion: class InvariantViolation: public std::logic_error { }; class InvariantChecker { public: InvariantChecker( boost::function< bool () > const& predicate): mPredicate( predicate ) { _check(); } ~InvariantChecker() { _check(); // may throw! What else to do? } private: void _check() const { if ( !mPredicate() ) { throw InvarianViolation(); } } boost::function< bool () > mPredicate; }; // usage example class IntStack { public: int pop() { InvariantChecker( boost::bind( std::greater_equal(), 0, mSize ); // check preconditions and do work. Then check postconditions. } private: int mSize; }; I don't know how to automatically implement the invariant check without throwing in the destructor of the InvariantChecker class. I know that is said everywhere to not throw exceptions in the destructor, but what other options are there to execute the check automatically at the start and end of a function? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: marcin.sfider on 29 Jun 2010 21:43 On Jun 29, 10:35 pm, Jens Auer <jens.muad...(a)googlemail.com> wrote: > I am trying to implement some tools to ease design by contract. To > check invariants automatically at the beginning and end of member > functions, I intend to use a helper object which does this in RAII- > fashion: > > class InvariantViolation: public std::logic_error > { > > }; > > class InvariantChecker > { > public: > InvariantChecker( boost::function< bool () > const& predicate): > mPredicate( predicate ) > { > _check(); > } > > ~InvariantChecker() > { > _check(); // may throw! What else to do? > } > > private: > void _check() const > { > if ( !mPredicate() ) > { > throw InvarianViolation(); > } > } > > boost::function< bool () > mPredicate; > > }; > > // usage example > class IntStack > { > public: > int pop() > { > InvariantChecker( boost::bind( std::greater_equal(), 0, mSize ); > // check preconditions and do work. Then check postconditions. > } > private: > int mSize; > > }; > > I don't know how to automatically implement the invariant check > without throwing in the destructor of the InvariantChecker class. I > know that is said everywhere to not throw exceptions in the > destructor, but what other options are there to execute the check > automatically at the start and end of a function? > The problem is that if the code between creation and destruction of InvariantChecker throws and then InvariantChecker destructor throws the program terminates and neither exception will do what it should. To work this out you could add try/catch after creation of each InvariantChecker like this: InvariantChecker ge_inv_check( boost::bind(std::greater_equal(), 0, mSize)); try { <your code here> } catch (...) { // tell the checker not to throw in destructor ge_inv_check.dontThrowInDestructor(); throw; } When wrapped with macros it could be useable I suppose. Cheers Sfider -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin B. on 29 Jun 2010 21:44 Jens Auer wrote: > I am trying to implement some tools to ease design by contract. To > check invariants automatically at the beginning and end of member > functions, I intend to use a helper object which does this in RAII- > fashion: > > class InvariantViolation: public std::logic_error > { > > }; > > class InvariantChecker > { > public: > InvariantChecker( boost::function< bool () > const& predicate): > mPredicate( predicate ) > { > _check(); > } > > ~InvariantChecker() > { > _check(); // may throw! What else to do? > } > I've never used uncaught_exception() myself, but if you wrap the _check() in if(!uncaught_exception()) then you can handle the case where your dtor is called for stack-unwind in case of exception. Or so I guess. :-) br, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Nick Hounsome on 29 Jun 2010 23:25 On 29 June, 21:35, Jens Auer <jens.muad...(a)googlemail.com> wrote: > I am trying to implement some tools to ease design by contract. To > check invariants automatically at the beginning and end of member > functions, I intend to use a helper object which does this in RAII- > fashion: > > class InvariantViolation: public std::logic_error > { > > }; > > class InvariantChecker > { > public: > InvariantChecker( boost::function< bool () > const& predicate): > mPredicate( predicate ) > { > _check(); > } > > ~InvariantChecker() > { > _check(); // may throw! What else to do? > } > > private: > void _check() const > { > if ( !mPredicate() ) > { > throw InvarianViolation(); > } > } > > boost::function< bool () > mPredicate; > > }; > > // usage example > class IntStack > { > public: > int pop() > { > InvariantChecker( boost::bind( std::greater_equal(), 0, mSize ); > // check preconditions and do work. Then check postconditions. > } > private: > int mSize; > > }; > > I don't know how to automatically implement the invariant check > without throwing in the destructor of the InvariantChecker class. I > know that is said everywhere to not throw exceptions in the > destructor, but what other options are there to execute the check > automatically at the start and end of a function? It's not a problem provided that you don't check invariants in the destructors of checked classes. The reason for not throwing in destructors is because of the effects of throwing whilst unwinding a stack due to a previous thrown exception - There is no logical way to handle this so the runtime has to call std::terminate. There should be no need to check in the destructor anyway. In fact it is would be logically wrong - If the invariant is checked on exit from every other method then it must be valid on entry to the dtor (barring random memory corruption) and also invariants are not usualy valid on exit from a dtor anyway because the object is destroyed. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Vladimir Jovic on 30 Jun 2010 22:23
Jens Auer wrote: > I don't know how to automatically implement the invariant check > without throwing in the destructor of the InvariantChecker class. I > know that is said everywhere to not throw exceptions in the > destructor, but what other options are there to execute the check > automatically at the start and end of a function? > Log the error (if possible with backtrace). Optionally, you can terminate the program. That will happen anyway, if you do not handle the exception in the destructor. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |