Boost logo

Boost :

Subject: [boost] [contract] concepts (was "Contract Programming Library")
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2010-04-15 11:50:26


On Wed, Feb 17, 2010 at 4:05 AM, Andrzej Krzemienski <akrzemi1_at_[hidden]> wrote:
>> > it is inevitable, etc., but.. read on. I know at least one library in
>> > Boost that also spoils function declarations in order to provide
>> > additional functionality: Concept Check library; they may be others
>> > too (MPL?).
>> > My suggestion is that if there are (or will be) libraries that require
>> > spoiling function declarations, they should all provide the same
>> > "spoiled" syntax. Otherwise I will be always asking "how do I declare
>> > a function in this library?". It would be very convenient if Boost
>> > provided one alternative function definition syntax that when used
>> > would enable all its libraries to work.
>>
>> I agree. However, in the past I did look into harmonizing my library
>> API with the ones of Boost.ConceptCheck and/or Boost.Parameter but it
>> did not seem feasible... I will double check it.
>
> This is not only about clarity. As a super-correct programmer I may want to
> apply both concept checking and pre-/post-conditions checking to my functions.
>
> Perhaps, if the 'compromise' syntax is possible, it requires changing
> concept-checking library.

I have verified that it is possible to use Boost.ConceptCheck together
with the current implementation of Boost.Contract as shown below. I
will look into doing something similar also for Boost.Parameter.

    #include <boost/concept_check.hpp>
    #include <boost/concept/requires.hpp>
    #include <contract.hpp>
    #include <iostream>

    struct x {

        CONTRACT_CLASS( (x) )

        template<typename T>
        BOOST_CONCEPT_REQUIRES(
            ((boost::Integer<T>)),
            (int))
        f(const T& x)
        CONTRACT_FUNCTION(
        (public) (template)( (typename)(T) )
        (int) (f)( (const T&)(x) )
            (precondition) ({
                CONTRACT_ASSERT( x >= 0 );
            })
            (postcondition) (result) ({
                CONTRACT_ASSERT( result == x );
            })
        (body) ({
            return x;
        }) )

    };

    int main() {
        x xx;
        std::cout << xx.f(123) << std::endl; // OK: Passes both
concept and contract checks.
    // std::cout << xx.f(1.23) << std::endl; // Error: Fails
concept check (compile-time).
    // std::cout << xx.f(-123) << std::endl; // Error: Fails
contract precondition check (run-time).
        return 0;
    }

This works because CONTRACT_FUNCTION() follows the function
declaration which can be spoiled by BOOST_CONCEPT_REQUIRES() as usual
to support concepts. However, I am planning to change
CONTRACT_FUNCTION() so the function declaration tokens do not need to
be repeated and I will add concept support following ConceptC++
syntax:

    CONTRACT_FUNCTION(
    (public) (template)( (typename)(T) )
        (requires)( (boost::Integer<T>) )
    (int) (f)( (const T&)(x) )
        (precondition)( (x >= 0) )
        (postcondition)(result)( (result == x) )
    ({
        return x;
    }) )

This will call Boost.ConceptCheck behind the scenes. Even after this
change to CONTRACT_FUNCTION(), Boost.Contract will still provide a
CONTRACT_FUNCTION_DEF() that will follow the function declaration (as
the current implementation of CONTRACT_FUNCTION() does). Therefore,
the example above where Boost.ConceptCheck is used directly can still
be programmed using the DEF() macro.

Lorenzo


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