
On Mon, Aug 27, 2012 at 1:05 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Mon, Aug 27, 2012 at 10:10 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 27/08/12 17:17, Lorenzo Caminiti a écrit :
On Sun, Aug 26, 2012 at 11:33 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 27/08/12 03:20, Lorenzo Caminiti a écrit :
On Sun, Aug 26, 2012 at 10:04 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 26/08/12 11:16, Vicente J. Botet Escriba a écrit :
= 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:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
I have read these notes. This seems to me a *hard* limitation and I would
Why "hard"? (For example, take a look to what Boost.Parameter requires to deal with constructs...)
You can just program the constructors with member initializers in the class declarations when using contracts:
CONTRACT_CLASS( class (x) ) { CONTRACT_CLASS_INVARIANT( void )
CONTRACT_CONSTRUCTOR( public (x) ( void ) initialize( a_(1), b_(2), c_(3) ) ) { ... // body right here }
private: int a_, b_, c_; };
If the body is really just too complex for an header... then you can always separate it with an init function (essentially, only the initializer list remains in the class declaration):
CONTRACT_CLASS( class (x) ) { CONTRACT_CLASS_INVARIANT( void )
CONTRACT_CONSTRUCTOR( public (x) ( void ) initialize( a_(1), b_(2), c_(3) ) ) { init(); // simple body }
private: void init ( void ); // deferred
private: int a_, b_, c_; };
// possibly in another file... void x::init ( void ) { ... // body now here (far from the declaration) }
You are right, hard was to strong ;-) Maybe the workaround merits to be include in the documentation.
Will do.
like you explain here deeply and broadly why, maybe someone could give you some ideas on alternatives.
With C++11 delegating constructors, this limitation /could/ be removed -- but I'm not sure because I didn't try. I will follow up with a separate email thread listing some snapshot of the generated code so we can discuss ideas and details :)
Yes, showing the generated code will help.
This might take me a couple of days because I'm busy with something else right now... stay tuned.
The CONSTRUCTOR macro in the following: CONTRACT_CLASS( template( typename T ) class (vector) ) { CONTRACT_CLASS_INVARIANT( void ) CONTRACT_CONSTRUCTOR( public (vector) ( (typename std::vector<T>::size_type) count ) initialize( vector_(count) ) ) {} public: std::vector<T> vector_; }; Expands to something like this (this is just an extract of the code): public : vector ( typename std::vector<T>::size_type count ) : ::contract::aux::call_constructor_entry< ERROR_missing_class_contract >( contract_auxXcontract_auxXconstructorXXsignature_traitsX13X ::type() , count , & ERROR_missing_class_contract :: contract_auxXstatic_class_invariantX , & ERROR_missing_class_contract :: contract_auxXcontract_auxXconstructorXXpreconditionX ) , vector_(count) { ::contract::aux::call_constructor_exit< contract_auxXcontract_auxXconstructorXXsignature_traitsX13X ::type >( & ERROR_missing_class_contract :: contract_auxXcontract_auxXconstructorXXbodyX , count , this , & ERROR_missing_class_contract :: contract_auxXstatic_class_invariantX , & ERROR_missing_class_contract :: ERROR_missing_class_invariant , & ERROR_missing_class_contract :: contract_auxXcontract_auxXconstructorXXoldofX ); } public : void contract_auxXcontract_auxXconstructorXXbodyX ( typename std::vector<T>::size_type count ) {} 1) I need an extra base class instantiation which depends on signature_traitsX13X (the extra base class checks pre before initializers). 13 is the macro expansion line number and that's known only at the declaration site (there' no way the CONSTRUCTOR_BODY macro can detect that). The signature_traitsX13X is needed to correctly handle overloaded functions/constructors. The CONSTRUCTOR_BODY macro can't reproduce the signature_traitsX13X because it doesn't know the constructor signature, just it's name. 2) I need to implement the destructor and then declare the body function. The CONSTRUCTOR_BODY macro can't do the body declaration part because it doesn't know the constructor signature, just it's name. template< typename T > CONTRACT_CONSTRUCTOR_BODY(vector<T>, vector) ( typename std::vector<T>::size_type count ) {} Expands to either: template< typename T > void vector<T>::contract_auxXcontract_auxXconstructorXXbodyX ( typename std::vector<T>::size_type count ) {} Or just the following when no contracts are disabled: template< typename T > void vector<T>::vector ( typename std::vector<T>::size_type count ) {} If I want to allow member initializers for separated constructor definitions then I have to complicate the BODY macro to take the entire constructor declaration again (not just the class type and name): CONTRACT_CONSTRUCTOR_BODY( template( typename T ) (vector<T>)(vector) ( (typename std::vector<T>::size_type) count ) initialize( vector_(count) ) ) {} So I can program signature_traits, the extra base class instantiation, the constructor body, and then the actual body function signature as done now by the CONTRACT_CONSTRUCTOR macro. But then the usual syntax propagates to the BODY macro as well :( Which delegating constructors I might be able to get around this issue by leaving the extra base class instatiation in the CONTRACT_CONSTRUCTOR macro expansion but then allowing the member initializers outside such a macro in the delegated constructor and therefore also after the BODY macro as the body function will no longer be a member function but it will be the delegated constructor... I'm not sure if I can actually do that... HTH, --Lorenzo