Boost logo

Boost :

Subject: Re: [boost] [contract] syntax redesign
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-11-08 04:50:02


On Sun, Nov 6, 2011 at 9:31 PM, Lorenzo Caminiti <lorcaminiti_at_[hidden]> wrote:
> On Tue, Oct 25, 2011 at 11:35 AM, Lorenzo Caminiti
> <lorcaminiti_at_[hidden]> wrote:
>> On Mon, Oct 24, 2011 at 7:01 PM, lcaminiti <lorcaminiti_at_[hidden]> wrote:
>>> Dave Abrahams wrote:
>>>> No, it's still too dense because of the comments (and the redundant
>>>> optional "namespace tag").  Try again, please :-)
>>> Sure, that's easy. Let me know if this still requires more work:
>
> I re-wrote all examples from Boost.Parameter using the proposed
> Boost.Contract syntax for named parameters (these named parameter
> examples don't compile yet):
>
> https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contract__/examples.html#contract__.examples.__named_parameters___depth_first_search__required_and_optional_named_parameters
>
> With named parameters for templates and constructors, Boost.Contract
> should be able to save the programmer from some boiler-plate code
> required instead by Boost.Parameter:
>
> https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contract__/examples.html#contract__.examples.__named_parameters___python__class___named_template_parameters
> https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contract__/examples.html#contract__.examples.__named_parameters___my_class__constructors_with_named_parameters
>
> This additional example mixes a bit more named parameters and contracts:
>
> https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contract__/examples.html#contract__.examples.__named_parameters___positive_number__fine_grained_parameter_name_control
>
> Comments are always welcome :)
>
> --Lorenzo
>

The following turned out to be a decent example that uses together a
bit of all the different features (contracts, concepts, and named
parameters) so I decided to cut-n-paste it here in an email:

#include <contract.hpp>
#include <boost/concept_check.hpp>
#include <boost/type_traits/has_equal_to.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/long.hpp>
#include <boost/mpl/char.hpp>
#include <iostream>

namespace num
{

namespace tag // Namespace `tag` already used here, use `keywords` instead.
{
    typedef int Value; // Dummy declarations...
    typedef boost::mpl::int_<1> Default;
    Value value = Default::value;
}

// Also use `Param` and `_param` postfixes instead of `_` prefix.
CONTRACT_TEMPLATE_PARAMETER((ValueParam, keywords) Value)
CONTRACT_TEMPLATE_PARAMETER((DefaultParam, keywords) Default)
CONTRACT_PARAMETER((value_param, keywords) value)

CONTRACT_CLASS(
template( // Named parameters.
    namespace keywords, // Use namespace `keywords` instead of `tag`.
    in typename Value, default int,
    in requires(is_same<boost::mpl::_::type, Value>) Default,
            default boost::mpl::int_<1>
) requires( boost::Copyable<Value> ) // Concepts.
struct (positive)
) {
    CONTRACT_CLASS_INVARIANT_TPL( // Contracts.
        static class(
            static_assert(Default::value > 0, "positive default value")
        ),
        get() > 0
    )

    CONTRACT_CONSTRUCTOR_TPL(
    public (positive) ( void )
        initialize( value_(Default::value) )
    ) {}

    CONTRACT_FUNCTION_TPL(
    public void (set) ( namespace keywords, in (Value const&) value )
        precondition( value > 0 )
        postcondition(
            get() == value, requires boost::has_equal_to<Value>::value
        )
    ) {
        value_ = value;
    }

    CONTRACT_FUNCTION_TPL(
    public (Value const&) (get) ( void ) const
    ) {
        return value_;
    }

private:
    Value value_;
};

} // namespace num

int main ( void )
{
    num::positive< char, boost::mpl::char_<'z'> > p;
    num::positive< > q;

    // Use `...Param` instead of `_...`.
    num::positive< num::DefaultParam< boost::mpl::int_<10> > > r;
    num::positive<
          num::DefaultParam< boost::mpl::long_<10> >
        , num::ValueParam<long>
> s;

    std::cout << s.get() << std::endl;
    s.set(num::value_param = 123); // Use `..._param` instead of `_...`.
    std::cout << s.get() << std::endl;

    return 0;
}

The goal here is to use Boost.Contract to /completely/ specify the
interface for the positive abstract data type.

--Lorenzo


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