Boost logo

Boost :

Subject: Re: [boost] [contract] syntax redesign
From: Dave Abrahams (dave_at_[hidden])
Date: 2011-11-08 22:35:45


on Tue Nov 08 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:

>> I presume this is essentially "typename Value=int".  I don't love
>> separating one argument with a comma that way.  Would
>>
>>  in typename (Value, int)
>> or something similar be practical?
>
> No because my syntax also supports non-variadic compilers

Oh!

> and the above will have to become (Value)(int) which forces extra
> parenthesis around (Value) even when there is no default. `...,
> default ...` is consistently used to indicate default parameter value
> (template or functional) and in my experience you get used to it
> pretty quickly.

I don't mind "default" at all, but the fact that it is separated by a
comma from "in typename Value", with no grouping to distinguish that
comma from the commas that separate parameters, is ugly. If it's the
only way to make it work, then so be it, but I'd prefer to have the
default value grouped somehow with the parameter name.

> In fact, I personally prefer Value, default int to (Value, int)
> (because in the second there is no description of the semantic of the
> 2nd token int).
>
>>>     in requires(is_same<boost::mpl::_::type, Value>) Default,
>>>             default boost::mpl::int_<1>
>>
>>
>> I don't understand what this is supposed to be saying.  Could you
>> explain it?
>
> This is a way of passing a named value template parameter by wrapping
> within a type template parameter as you suggested...

Well, it may be, but I don't understand how it works.

> is there a better way to do this? I want to pass:
>
> template< typename Value, Value default_value = 1 >
>
> Where both Value and default_value are named using Boost.Parameter.

If I were you I would try to think a little beyond the limitations of
Boost.Parameter. If there's an interface we can implement that better
supports this use-case, we'll add it. Is there?

>> Have you thought of using decltype in the implementation, to avoid
>> writing ::type up there?
>
> I'm not using C++1 features. (The C++11-looking auto, static_assert,
> etc that you see in Boost.Contract are all handled by the pp and
> implemented using C++03.)

Wow! But decltype might be (a little) different, since we can emulate
it with Boost.Typeof. Just something to consider.

>> Something like boost::mpl::_::type seems like maybe it should be
>> spelled "auto" (if possible).
>
> It cannot because it is nested inside the named parameter type
> predicate so the pp has to way to parse it.

Right. Well, boost::contract::auto_ then? I know, yuck :-P

> ::type is needed because I am using a type to wrap a value so the
> value template parameter can be named (as indicated above).

I don't understand what you're saying here yet.

>>> ) requires( boost::Copyable<Value> ) // Concepts.
>>> struct (positive)
>>> ) {
>>>     CONTRACT_CLASS_INVARIANT_TPL( // Contracts.

Because it's an invariant for a class template, not an invariant
template. At least, IIUC.

>> Why is that a better spelling than CONTRACT_CLASS_TPL_INVARIANT?
>>
>>>         static class(
>>>             static_assert(Default::value > 0, "positive default value")
>>>         ),
>>
>> I don't understand what the "static class(...)" construct is doing here.
>
> This will be detailed in Boost.Contract docs (it's an addition over
> N1962). All assertions within static class(...) specify /static class
> invariants/. (Non-static) class invariants are not checked at
> entry/exit of static functions or at constructor entry. However,
> static class invariants are also checked at entry/exit of static
> functions and at constructor entry.

Hm, OK.

> Obviously, static class invaraints cannot refer to the object (but
> only to static member data/functions). In addition, this one static
> class invariant is using a static assertion (for this example, given
> that the assertion is static it could also have been programmed as
> part of the non-static class invariants and get the same type of
> checking which is always at compile-time for static_assert).

[OK. It would be good to have an example in the end product that doesn't
include that kind of redundancy.]

> Static class invariants were discussed with N1962 authors 1+ years ago
> over the Boost ML (no one had objections on them but no one seemed to
> think they will be useful in real life).

In that case, I think you should omit them. Premature generalization is
the root of all evil ;-)

>>>         get() > 0 )
>>>
>>>     CONTRACT_CONSTRUCTOR_TPL(
>>>     public (positive) ( void )
>>
>> Is "void" mandatory here?
>
> No if your compiler supports empty macro parameters or variadics.
> However, often MSVC (which in theory supports both) gets confused and
> generates pp-error. So I always use void to indicate and empty
> (parameter) list so the code is most portable.

Ah.

>>>         initialize( value_(Default::value) ) ) {}
>>
>> What is "value_"?
>
> A private member variable.

OK, thanks.

>>>     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
>>
>> Why must ::value appear in the previous line?
>
> Because assertion requirements are specified using integral static
> constants and not nullary metafunctions. This could be (esaily)
> changed to be more consistent with named parameter requires that uses
> unary metafunctions... I'll think about it.

Please do.

>> This is very nice, but still could use some explanation and
>> simplification.
>
> Explanation will definitely go in the docs. What simplifications would
> you suggest?

E.g. leaving out the "namespace" stuff and the features that nobody
thinks will be useful.

-- 
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

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