Re: [boost] [contract] Released Contract Programming Library on SourceForge

I have released on SourceForge a library that implements Contract Programming (a.k.a. Design by Contract(TM) ) for C++. I am considering to submit this library to Boost (as Boost.Contract). Comments?
Hi, Just another thought for a tiny extension that came to my mind. I tried to use the block invariant as a regular assert: int main() { CONTRACT_ASSERT_BLOCK_INVARIANT( fee fee fee ); } This code compiles and works fine. This is because "disabling block invariants" means that the entire macro invocation will disappear, inclusive of the nonsense I wrote inside. We are used to it because this is how C-style asserts work, but one of the advantage of asserts over comments, as it is often advertised, is that the predicates are checked for syntactic and (to some extent) semantic correctness. But this is not the case if we disable the assertion macros. I believe, it would be useful if "disabling block invariants" meant no run-time overhead, but still checking syntactic correctness. It would be possible if the macro CONTRACT_ASSERT_BLOCK_INVARIANT( expression ); were replaced with something like: ... sizeof( expression ) ... then, the expression is not evaluated, but required to be correct. If the value of sizeof is not used it should be eliminated by the compiler. Obviously, the same would be applicable for all the other types of checks, Regards, &rzej

Hello Andrzej, I understand your suggestion but not fully removing the contract macros has the following key disadvantages: 1) It still increases compile-time. During development, I find it useful to be able to *completely* strip the contracts away, including from compilation -- it saves me from waiting extra time to compile contract code that I am not executing yet. 2) Inv, pre, and post conditions are programmed by the library in private member functions (the assertions cannot appear in the body because the body might be defined in .cpp separated from the contract declaration). I think compilation of these extra member functions will still increase the object size (even if if these functions are private, called by no one, and they only contain statements like `sizeof(expression)` that have no effect) -- I have not verified this. Plus, you can always make sure the contracts are syntactically correct by deliberately compiling with all contract on every so often. Therefore, I will keep the current design that expands the contract macros to nothing when contract compilation is off. I will make this reasoning clear in the documentation. On Sun, Feb 28, 2010 at 4:57 PM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
this is how C-style asserts work, but one of the advantage of asserts over comments, as it is often advertised, is that the predicates are checked for syntactic and (to some extent) semantic correctness. But this is not the case if we disable the assertion macros.
The Contract Programming benefit usually advertised as "trustworthy documentation" (see [Meyer1997]) is gained only when contracts are compiled and *executed* during testing so they are checked not just syntactically but also semantically by the test suite.
be possible if the macro
CONTRACT_ASSERT_BLOCK_INVARIANT( expression );
were replaced with something like:
... sizeof( expression ) ...
then, the expression is not evaluated, but required to be correct. If the value of sizeof is not used it should be eliminated by the compiler. Obviously, the same would be applicable for all the other
BTW, [Stroustrup1997] suggests to use `Assert(!CONTRACT_CHECK_BLOCK_INVARIANT || expression)` to implement a similar functionality.

Hello, On Sun, Feb 28, 2010 at 5:57 PM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
I believe, it would be useful if "disabling block invariants" meant no run-time overhead, but still checking syntactic correctness. It would be possible if the macro
Please see a couple of clarifications on this topic below. On Mon, Mar 8, 2010 at 9:39 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
1) It still increases compile-time. During development, I find it useful to be able to *completely* strip the contracts away, including from compilation -- it saves me from waiting extra time to compile contract code that I am not executing yet.
In general, it is difficult to assess how much compilation-time will actually go into the contract assertions because that depends on the complexity and number of the assertions. This will be different from project to project. For a real project I have worked on (~60,000 lines of C++), disabling assertion compilation reduced compilation-time of about 10%. For that project, this saving was significant. However, for other projects this type of saving might not be significant and always checking the assertion syntax might be more relevant.
2) Inv, pre, and post conditions are programmed by the library in private member functions (the assertions cannot appear in the body because the body might be defined in .cpp separated from the contract declaration). I think compilation of these extra member functions will still increase the object size (even if if these functions are private, called by no one, and they only contain statements like `sizeof(expression)` that have no effect) -- I have not verified this.
I have verified this point and I was incorrect. Based on the example I listed below, the compiler can strip the private/never called contract function containing the assertions (postconditions in this case). Therefore, there should be no object code size increase and no run-time execution overhead even when always checking assertion syntax. (I will eventually need to confirm this 100% if I implement it in the library.) One detail is that, when contracts are *all* turned off, the library #include <contract.hpp> could only include the preprocessing macros and none of the library templates so to reduce the object code size. This will not be possible when always checking assertion syntax because the library contract::noold and other templates will need to be available to program the contract functions wrapping the assertions. Therefore, in the case of all contracts turned off, always checking assertion syntax will increase a bit the object-size. However, I think this is not a big deal (only a few of the library templates will actually be needed). In summary, given that: a) The only cost of always checking assertion syntax is extra compilation-time (but there is no run-time/object-size overhead). b) Compiling the assertions might take different time for different projects. [c) Also given the popular responses to the "[boost] suggestion on assertion macros" email thread...] I think I should at least consider offering this feature via a configuration macro. For example, if CONTRACT_CONFIG_ALWAYS_CHECK_SYNTAX is 1/0 the contract assertions will always/not-always be compiled to check their syntax. This way programmers can decide if they can sacrifice some of their compilation time for this feature or not. What should be CONTRACT_CONFIG_ALWAYS_CHECK_SYNTAX default value? 0 or 1? (Maybe 1...) I will add this to the library TODO list. OBJECT-SIZE ANALYSIS // File: check.cpp #include <contract.hpp> class c { public: struct s {}; void f(const s& a) {} #ifdef CONTRACT_ALWAYS_CHECK_SYNTAX private: // See Without the Macros section in the documentation... template< int ZERO > void contract_postcondition_f_a_( contract::noold, typename contract::aux::arg< const s& >::type a, contract::noold ) const { CONTRACT_ASSERT( true ); } public: #endif }; int main() { c().f(c::s()); return 0; } Check syntax on: $ g++ -Wall -Werror -I./src -DCONTRACT_CHECK_BLOCK_INVARIANT -DCONTRACT_CHECK_CLASS_INVARIANT -DCONTRACT_CHECK_PRECONDITION -DCONTRACT_CHECK_POSTCONDITION -DCONTRACT_ALWAYS_CHECK_SYNTAX ./test/check/main.cpp -o check $ ls -l check -rwxr-xr-x 1 lcaminiti lcaminiti 8341 2010-03-21 11:52 check $ size check text data bss dec hex filename 2051 316 8 2375 947 check Note the syntax error in case `CONTRACT_ASSERT( true );` is replaced with `CONTRACT_ASSERT( truex );`: $ g++ -Wall -Werror -I./src -DCONTRACT_CHECK_BLOCK_INVARIANT -DCONTRACT_CHECK_CLASS_INVARIANT -DCONTRACT_CHECK_PRECONDITION -DCONTRACT_CHECK_POSTCONDITION -DCONTRACT_ALWAYS_CHECK_SYNTAX ./test/check/main.cpp -o check ./test/check/main.cpp: In member function ‘void c::contract_postcondition_f_a_(contract::noold, const c::s&, contract::noold) const’: ./test/check/main.cpp:17: error: ‘truex’ was not declared in this scope Check syntax off (same `size check` results as above): $ g++ -Wall -Werror -I./src -DCONTRACT_CHECK_BLOCK_INVARIANT -DCONTRACT_CHECK_CLASS_INVARIANT -DCONTRACT_CHECK_PRECONDITION -DCONTRACT_CHECK_POSTCONDITION -UCONTRACT_ALWAYS_CHECK_SYNTAX ./test/check/main.cpp -o check $ ls -l check -rwxr-xr-x 1 lcaminiti lcaminiti 8341 2010-03-21 11:53 check $ size check text data bss dec hex filename 2051 316 8 2375 947 check Note no syntax error in case `CONTRACT_ASSERT( true );` is replaced with `CONTRACT_ASSERT( truex );`: $ g++ -Wall -Werror -I./src -DCONTRACT_CHECK_BLOCK_INVARIANT -DCONTRACT_CHECK_CLASS_INVARIANT -DCONTRACT_CHECK_PRECONDITION -DCONTRACT_CHECK_POSTCONDITION -UCONTRACT_ALWAYS_CHECK_SYNTAX ./test/check/main.cpp -o check Regards, Lorenzo
participants (2)
-
Andrzej Krzemienski
-
Lorenzo Caminiti