Boost logo

Boost :

Subject: Re: [boost] [Review:Contract] Some questions
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2012-08-26 21:20:50

On Sun, Aug 26, 2012 at 10:04 AM, Vicente J. Botet Escriba
<vicente.botet_at_[hidden]> wrote:
> Le 26/08/12 11:16, Vicente J. Botet Escriba a écrit :
> Hi,
>> First of all, thanks Lorenzo for your work on pre-processor programming.
>> With this library, you have showed to me how far the pre-processing can go
>> in terms of expressiveness.
>> I have some questions before doing a complete the review:
> Hi again,
> more comments and questions follows
> = member initializers =
> Why the following limitation?
> "Unfortunately, when member initializers are specified, the constructor body
> must be defined together with its declaration and contract."

See note 34:

> = C++03 limitations =
> It would be great if you add a section/table with all the limitations, as
> e.g. these ones

Will do.

> * Function and array types cannot be directly used as function parameter
> types within the contract macros ...
> * Each function parameter must always specify both its type and its name
> (parameter names can instead by omitted in usual C++ declarations).
> * All tokens must be specified in the fixed order listed in the Grammar
> section (it is not possible to specify postconditions before preconditions,
> |volatile| before |const| for member functions, etc).
> * Unfortunately, this library does not allow to specify contracts for
> unions.
> * Unfortunately, when member initializers are specified, the constructor
> body must be defined together with its declaration and contract
> and use some kind of as Warning or Important when documenting them.
> = use of deferred =
> IMO deferred is related to the time dimension, while I think you are using
> it on the space dimension. "The function body definition can be separated"
> is OK, but deferred :(

I tough deferred is standard terminology in this context (I even
double-check it somewhere a couple of years back)... maybe I'm
wrong... I'm happy to use whatever the standard terminology is for a
function that is defined in a place different from which it is first

> = _BODY macros =
> Why do you need to make a difference between CONTRACT_FREE_BODYand

See note 32:

> What if the user uses CONTRACT_FREE_BODYwhen it should use
> CONTRACT_MEMBER_BODY? It will not have the associated class invariants.

No, but when you partially disable contracts you might get
compiler-errors like "function ...XbodyXpush_back is not defined...".

> The user will see this error very late when she realize that the function is
> breaking a class invariant (by other means).
> I think it will be better if the syntax forces an error in this case. What
> about
> template< typename T, T Default >
> bool CONTRACT_MEMBER_BODY((natural<T, Default>),equal) ( natural const&
> right )
> const
> {
> return not less(*this, right) && not greater(*this, right);
> }
> This will make more homogeneous |CONTRACT_CONSTRUCTOR_BODY|,
> What do you think?

It used to be MEMBER_BODY(func_name), then it was
MEMBER_BODY(class_type, func_name), and now it's back to
MEMBER_BODY(func_name) ;) See note 47:

> = ( void ) || empty macro parameters =
> |
> For projects that don't care about portability, or just use compilers that
> supports the | empty macro parameters it will be great if they can use ()
> instead of ( void ) to represent no parameters.
> Could you provide this?

On a decent pp (g++), ( ) should work instead of ( void ). The lib
implementation should supports both (even if this complicates the
implementation and I didn't fully test () ) -- I'll state this in the

> = _TPL macros and performance =
> Could you give some figures of the gain of the change of introducing the
> _TPL macros?

No, I don't have the numbers :( Now it'll be too much work to
implement the without _TPL case to compare... However, the without
_TPL implementation created an extra 4 template functions for each
user defined functions. In the _TPL case the extra 4 functions are
template functions only when the user function is also a template.

> = Static assertions =
> What is the interest of disabling static assertion when
> defined?

Not sure... I wondered this myself. I guess such static assertions for
pre/post/inv are a new feature so it's just my best guess. Allowing to
disable a precondition static assertion when you disable precondition
made some sense to me -- otherwise, what will be the difference
between a static assertion in preconditions, postconditions, or class
invariants? or even within the body itself? However, I thought about
this and I wan't 100% sure either way... I'm happy to discuss this
requirement more.

> = return =
> ^" *Rationale.* The result type needs to be copyable in order for the
> function itself to return a value so this library can always evaluate return
> value declarations."
> This is only true if rvalue references are not supported. Otherwise, for
> MovableOnly types the variable used to store the return value could be a
> rvalue reference and move semantics should be applied.
> Even if you don't support C++11, the user can use Boost.Move.

I think so. I don't mention rvalues at all (emulated nor C++11) in the
docs... I can add a few notes about rvalues when supporting C++11.


Boost list run by bdawes at, gregod at, cpdaniel at, john at