[Review:Contract] Some questions

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: = C++11 compatibility = * Does the library use c++11 features when available? I was thinking e.g. on the emulated virtual specifiers. BTW, I think the "new" virtual specifier was removed from the standard, but maybe I'm wrong. * I think the library don't allow to declare C++11 specific classes/function. E.g * variadic templates * noexcept functions * constexpr functions * class/function attributes BTW, I have not see any example using exception specifications using 'throws'. Does the library support them? Could you confirm? and if not, could you tell us if you have a plan to support them? = Postconditions result = "Postconditions can access the function return value by declaring a variable of type |auto| and assigning it to the |return| keyword (the variable name is arbitrary but |result| is often used)." What prevent the library to the use of return instead of an auto variable postcondition( // Postconditions. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... return == old_value ) instead of postcondition( // Postconditions. auto result = return, // Result value. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... result == old_value ) =Constant assertions = I would expect that the old are always const so the following postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even, old_even ) even == old_even + 2, const( odd, old_odd ) odd == old_odd + 2 ) should be rewritten without loss of semantics as postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even ) even == old_even + 2, const( odd ) odd == old_odd + 2 ) = Oldof = As the old of value must be declared using a variable, using a specif oldof keyword that will replace auto old_size = CONTRACT_OLDOF size(), by oldofold_size = size(), could simplify the syntax. What do you think? Some minor points: * Why do you use( void ) instead of () in the functions without parameters? e.g. public: bool empty ( void ) const { return vector_.empty(); } Some suggestions: * Use 2 spaces indentation instead of 4 could reduce the width of the page, in particular when you use several columns. * The use of'int const' as return type is verbose and could be replaced by just int. Best, Vicente

Le 26/08/12 11:16, Vicente J. Botet Escriba a écrit : The access to the files linked from the documentation as in Header <contract/body.hpp <http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_0_4_1//contract/body.hpp>> fail. Could you add the files? Vicente

On Sun, Aug 26, 2012 at 7:07 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 26/08/12 11:16, Vicente J. Botet Escriba a écrit :
The access to the files linked from the documentation as in
Header <contract/body.hpp
fail. Could you add the files?
All the header files links in the Reference section are broken :( They point to: release/contract_0_4_1/contract/... But the files actually are in (note the extra include dir): release/contract_0_4_1/include/contract/... I've created a ticket and I'll fix this later on. For now, please take a look at the files from the include dir manually. Thanks, --Lorenzo

Hi, On Sun, Aug 26, 2012 at 2:16 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
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.
Welcome :)
I have some questions before doing a complete the review:
= C++11 compatibility =
* Does the library use c++11 features when available? I was thinking e.g. on the emulated virtual specifiers. BTW, I think the "new" virtual specifier was removed from the standard, but maybe I'm wrong. * I think the library don't allow to declare C++11 specific classes/function. E.g * variadic templates * noexcept functions * constexpr functions * class/function attributes
The library is written for C++03 for now, while it emulates some C++11 features for C++03, the library doesn't support all C++11 features and doesn't take advantage (go native) of them when available instead of the emulated features. I am planning to extend the library to support C++11 (the declaration syntax should be extendible without any problem). I've added a ticket https://sourceforge.net/apps/trac/contractpp/ticket/61
BTW, I have not see any example using exception specifications using 'throws'. Does the library support them?
Yes, for example: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Could you confirm? and if not, could you tell us if you have a plan to support them?
= Postconditions result =
"Postconditions can access the function return value by declaring a variable of type |auto| and assigning it to the |return| keyword (the variable name is arbitrary but |result| is often used)."
What prevent the library to the use of return instead of an auto variable
postcondition( // Postconditions. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... return == old_value )
This won't work if return is not the 1st token: old_value == return 3 + return myfync(return) etc because there's no way the preprocessor can skip the leading tokens given that they are unknown :( and they could contain symbols. I will clarify this point in the rationale.
instead of
postcondition( // Postconditions. auto result = return, // Result value. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... result == old_value )
=Constant assertions =
I would expect that the old are always const so the following
postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even, old_even ) even == old_even + 2, const( odd, old_odd ) odd == old_odd + 2 )
old_... are const but you need to specify them in const( ... ) so they can be accessed by the constant-assertion boolean condition: const( var1, var2, ... ) boolean-condition-using-var1-var2-... only global/static variables and var1, var2, etc can be used by boolean-condition-using-var1-var2-... The docs are not clear abut this point, I'll clarify it.
should be rewritten without loss of semantics as
postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even ) even == old_even + 2, const( odd ) odd == old_odd + 2 )
= Oldof =
As the old of value must be declared using a variable, using a specif oldof keyword that will replace
auto old_size = CONTRACT_OLDOF size(), by
oldofold_size = size(),
This wont' work because the pp can't separate the trailing size() expression for the rest because it can't deal with unknown tokens and symbols like "size()" or "old_size". The expression: auto old_size = CONTRACT_OLDOF size() is parsed into type "auto", assignment "old_size =" (note that the pp can't separate the = because it's a symbol and that required lots of tricks to be handled correctly...), and the expression "size()". I need all these separate traits to handle old-values while: oldofold_size = size() and even: oldof old_size = size() can't separate "old_size = size()" into "old_size" and "size()". The macro CONTRACT_OLDOF expands into )( so at some point in the CONTRACT_FUNCTION expansion this: CONTRACT_FUNCTION( ... auto old_size = CONTRACT_OLDOF size() ... ) expands to (auto is know or wrapped within parenthesis the user): (auto) (old_size =) (size()) which is ultimately a sequence and it can be handled by the pp.
could simplify the syntax. What do you think?
Some minor points:
* Why do you use( void ) instead of () in the functions without parameters? e.g.
public: bool empty ( void ) const { return vector_.empty(); }
Because MSVC pp gets confused with () even on C++11. On G++ you can use () but the code might not always compile with MSVC :( http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Some suggestions:
* Use 2 spaces indentation instead of 4 could reduce the width of the page, in particular when you use several columns. * The use of'int const' as return type is verbose and could be replaced by just int.
Thanks, --Lorenzo

Hi,
On Sun, Aug 26, 2012 at 2:16 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
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. Welcome :)
I have some questions before doing a complete the review:
= C++11 compatibility =
* Does the library use c++11 features when available? I was thinking e.g. on the emulated virtual specifiers. BTW, I think the "new" virtual specifier was removed from the standard, but maybe I'm wrong. * I think the library don't allow to declare C++11 specific classes/function. E.g * variadic templates * noexcept functions * constexpr functions * class/function attributes The library is written for C++03 for now, while it emulates some C++11 features for C++03, the library doesn't support all C++11 features and doesn't take advantage (go native) of them when available instead of the emulated features. I am planning to extend the library to support C++11 (the declaration syntax should be extendible without any problem). I've added a ticket https://sourceforge.net/apps/trac/contractpp/ticket/61 I guess it will be better to have a ticket for each planned feature, so
Le 26/08/12 18:24, Lorenzo Caminiti a écrit : that they can be delivered one by one. For people that are using C++11, this could be a show-stopper for the library adoption, and IMO there are more and more that are moving to C++11.
BTW, I have not see any example using exception specifications using 'throws'. Does the library support them? Yes, for example: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Thanks, I have not yet read this part.
Could you confirm? and if not, could you tell us if you have a plan to support them?
= Postconditions result =
"Postconditions can access the function return value by declaring a variable of type |auto| and assigning it to the |return| keyword (the variable name is arbitrary but |result| is often used)."
What prevent the library to the use of return instead of an auto variable
postcondition( // Postconditions. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... return == old_value ) This won't work if return is not the 1st token:
old_value == return 3 + return myfync(return) etc
because there's no way the preprocessor can skip the leading tokens given that they are unknown :( and they could contain symbols. I will clarify this point in the rationale. OK. I understand.
instead of
postcondition( // Postconditions. auto result = return, // Result value. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... result == old_value )
=Constant assertions =
I would expect that the old are always const so the following
postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even, old_even ) even == old_even + 2, const( odd, old_odd ) odd == old_odd + 2 ) old_... are const but you need to specify them in const( ... ) so they can be accessed by the constant-assertion boolean condition:
const( var1, var2, ... ) boolean-condition-using-var1-var2-... Why? only global/static variables and var1, var2, etc can be used by boolean-condition-using-var1-var2-... The docs are not clear abut this point, I'll clarify it.
should be rewritten without loss of semantics as
postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even ) even == old_even + 2, const( odd ) odd == old_odd + 2 )
= Oldof =
As the old of value must be declared using a variable, using a specif oldof keyword that will replace
auto old_size = CONTRACT_OLDOF size(), by
oldofold_size = size(), This wont' work because the pp can't separate the trailing size() expression for the rest because it can't deal with unknown tokens and symbols like "size()" or "old_size". The expression:
auto old_size = CONTRACT_OLDOF size()
is parsed into type "auto", assignment "old_size =" (note that the pp can't separate the = because it's a symbol and that required lots of tricks to be handled correctly...), and the expression "size()". I need all these separate traits to handle old-values while:
oldofold_size = size()
and even:
oldof old_size = size()
can't separate "old_size = size()" into "old_size" and "size()". The macro CONTRACT_OLDOF expands into )( so at some point in the CONTRACT_FUNCTION expansion this:
CONTRACT_FUNCTION( ... auto old_size = CONTRACT_OLDOF size() ... )
expands to (auto is know or wrapped within parenthesis the user):
(auto) (old_size =) (size())
which is ultimately a sequence and it can be handled by the pp. OK, I understand why you did this way now.
could simplify the syntax. What do you think?
Some minor points:
* Why do you use( void ) instead of () in the functions without parameters? e.g.
public: bool empty ( void ) const { return vector_.empty(); } Because MSVC pp gets confused with () even on C++11. On G++ you can use () but the code might not always compile with MSVC :(
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... Note that the preceding example was just a function declaration with no macros, so I guess MSVC will be able to take care of
bool empty ( ) const; isn't it? Best, Vicente

On Sun, Aug 26, 2012 at 10:00 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 26/08/12 18:24, Lorenzo Caminiti a écrit :
Hi,
On Sun, Aug 26, 2012 at 2:16 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
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.
Welcome :)
I have some questions before doing a complete the review:
= C++11 compatibility =
* Does the library use c++11 features when available? I was thinking e.g. on the emulated virtual specifiers. BTW, I think the "new" virtual specifier was removed from the standard, but maybe I'm wrong. * I think the library don't allow to declare C++11 specific classes/function. E.g * variadic templates * noexcept functions * constexpr functions * class/function attributes
The library is written for C++03 for now, while it emulates some C++11 features for C++03, the library doesn't support all C++11 features and doesn't take advantage (go native) of them when available instead of the emulated features. I am planning to extend the library to support C++11 (the declaration syntax should be extendible without any problem). I've added a ticket https://sourceforge.net/apps/trac/contractpp/ticket/61
I guess it will be better to have a ticket for each planned feature, so that they can be delivered one by one. For people that are using C++11, this could be a show-stopper for the library adoption, and IMO there are more and more that are moving to C++11.
Once I start supporting C++11 (which I could do before an eventual Boost release), it should be easy enough to support *all* C++11 extra declaration features at once. In most cases the lib has to simply parse the pp syntax and generate the C++11 native code under-nit.
BTW, I have not see any example using exception specifications using 'throws'. Does the library support them?
Yes, for example:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Thanks, I have not yet read this part.
Could you confirm? and if not, could you tell us if you have a plan to support them?
= Postconditions result =
"Postconditions can access the function return value by declaring a variable of type |auto| and assigning it to the |return| keyword (the variable name is arbitrary but |result| is often used)."
What prevent the library to the use of return instead of an auto variable
postcondition( // Postconditions. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... return == old_value )
This won't work if return is not the 1st token:
old_value == return 3 + return myfync(return) etc
because there's no way the preprocessor can skip the leading tokens given that they are unknown :( and they could contain symbols. I will clarify this point in the rationale.
OK. I understand.
instead of
postcondition( // Postconditions. auto result = return, // Result value. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... result == old_value )
=Constant assertions =
I would expect that the old are always const so the following
postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even, old_even ) even == old_even + 2, const( odd, old_odd ) odd == old_odd + 2 )
old_... are const but you need to specify them in const( ... ) so they can be accessed by the constant-assertion boolean condition:
const( var1, var2, ... ) boolean-condition-using-var1-var2-...
Why?
Because constant-assertions are implemented using local functions which have such a limitation. Essentially, constant-assertions are local function's constant blocks: http://www.boost.org/doc/libs/1_51_0/libs/local_function/doc/html/boost_loca... I'll document this rationale.
only global/static variables and var1, var2, etc can be used by boolean-condition-using-var1-var2-... The docs are not clear abut this point, I'll clarify it.
should be rewritten without loss of semantics as
postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even ) even == old_even + 2, const( odd ) odd == old_odd + 2 )
= Oldof =
As the old of value must be declared using a variable, using a specif oldof keyword that will replace
auto old_size = CONTRACT_OLDOF size(), by
oldofold_size = size(),
This wont' work because the pp can't separate the trailing size() expression for the rest because it can't deal with unknown tokens and symbols like "size()" or "old_size". The expression:
auto old_size = CONTRACT_OLDOF size()
is parsed into type "auto", assignment "old_size =" (note that the pp can't separate the = because it's a symbol and that required lots of tricks to be handled correctly...), and the expression "size()". I need all these separate traits to handle old-values while:
oldofold_size = size()
and even:
oldof old_size = size()
can't separate "old_size = size()" into "old_size" and "size()". The macro CONTRACT_OLDOF expands into )( so at some point in the CONTRACT_FUNCTION expansion this:
CONTRACT_FUNCTION( ... auto old_size = CONTRACT_OLDOF size() ... )
expands to (auto is know or wrapped within parenthesis the user):
(auto) (old_size =) (size())
which is ultimately a sequence and it can be handled by the pp.
OK, I understand why you did this way now.
could simplify the syntax. What do you think?
Some minor points:
* Why do you use( void ) instead of () in the functions without parameters? e.g.
public: bool empty ( void ) const { return vector_.empty(); }
Because MSVC pp gets confused with () even on C++11. On G++ you can use () but the code might not always compile with MSVC :(
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Note that the preceding example was just a function declaration with no macros, so I guess MSVC will be able to take care of
bool empty ( ) const;
isn't it?
Oops, no macros... so sure you can use empty ( ) instead of empty ( void ) but I'm always using a C++ declaration syntax that looks more closely to the library's declaration syntax so programmers get more familiar with it (e.g., ( void ), public:, etc). I'll mention this rationale in the docs. Thanks, --Lorenzo

Le 27/08/12 02:55, Lorenzo Caminiti a écrit :
Le 26/08/12 18:24, Lorenzo Caminiti a écrit :
Hi,
On Sun, Aug 26, 2012 at 2:16 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
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. Welcome :)
I have some questions before doing a complete the review:
= C++11 compatibility =
* Does the library use c++11 features when available? I was thinking e.g. on the emulated virtual specifiers. BTW, I think the "new" virtual specifier was removed from the standard, but maybe I'm wrong. * I think the library don't allow to declare C++11 specific classes/function. E.g * variadic templates * noexcept functions * constexpr functions * class/function attributes The library is written for C++03 for now, while it emulates some C++11 features for C++03, the library doesn't support all C++11 features and doesn't take advantage (go native) of them when available instead of the emulated features. I am planning to extend the library to support C++11 (the declaration syntax should be extendible without any problem). I've added a ticket https://sourceforge.net/apps/trac/contractpp/ticket/61 I guess it will be better to have a ticket for each planned feature, so that they can be delivered one by one. For people that are using C++11, this could be a show-stopper for the library adoption, and IMO there are more and more that are moving to C++11. Once I start supporting C++11 (which I could do before an eventual Boost release), it should be easy enough to support *all* C++11 extra declaration features at once. In most cases the lib has to simply
On Sun, Aug 26, 2012 at 10:00 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote: parse the pp syntax and generate the C++11 native code under-nit.
BTW, I have not see any example using exception specifications using 'throws'. Does the library support them? Yes, for example:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... Thanks, I have not yet read this part.
Could you confirm? and if not, could you tell us if you have a plan to support them?
= Postconditions result =
"Postconditions can access the function return value by declaring a variable of type |auto| and assigning it to the |return| keyword (the variable name is arbitrary but |result| is often used)."
What prevent the library to the use of return instead of an auto variable
postcondition( // Postconditions. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... return == old_value ) This won't work if return is not the 1st token:
old_value == return 3 + return myfync(return) etc
because there's no way the preprocessor can skip the leading tokens given that they are unknown :( and they could contain symbols. I will clarify this point in the rationale. OK. I understand.
instead of
postcondition( // Postconditions. auto result = return, // Result value. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... result == old_value )
=Constant assertions =
I would expect that the old are always const so the following
postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even, old_even ) even == old_even + 2, const( odd, old_odd ) odd == old_odd + 2 ) old_... are const but you need to specify them in const( ... ) so they can be accessed by the constant-assertion boolean condition:
const( var1, var2, ... ) boolean-condition-using-var1-var2-... Why? Because constant-assertions are implemented using local functions which have such a limitation. Essentially, constant-assertions are local function's constant blocks: http://www.boost.org/doc/libs/1_51_0/libs/local_function/doc/html/boost_loca... I'll document this rationale.
I understand now why all the used variables need to be declared. I don't think I will use it to prevent from constness errors. Note that reversing the arguments in assertions/checks is a good practice: old_odd + 2 == odd How this const local functions relates to c++11 lambda expressions? Best, Vicente

On Sun, Aug 26, 2012 at 11:49 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 27/08/12 02:55, Lorenzo Caminiti a écrit :
On Sun, Aug 26, 2012 at 10:00 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 26/08/12 18:24, Lorenzo Caminiti a écrit :
Hi,
On Sun, Aug 26, 2012 at 2:16 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
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.
Welcome :)
I have some questions before doing a complete the review:
= C++11 compatibility =
* Does the library use c++11 features when available? I was thinking e.g. on the emulated virtual specifiers. BTW, I think the "new" virtual specifier was removed from the standard, but maybe I'm wrong. * I think the library don't allow to declare C++11 specific classes/function. E.g * variadic templates * noexcept functions * constexpr functions * class/function attributes
The library is written for C++03 for now, while it emulates some C++11 features for C++03, the library doesn't support all C++11 features and doesn't take advantage (go native) of them when available instead of the emulated features. I am planning to extend the library to support C++11 (the declaration syntax should be extendible without any problem). I've added a ticket https://sourceforge.net/apps/trac/contractpp/ticket/61
I guess it will be better to have a ticket for each planned feature, so that they can be delivered one by one. For people that are using C++11, this could be a show-stopper for the library adoption, and IMO there are more and more that are moving to C++11.
Once I start supporting C++11 (which I could do before an eventual Boost release), it should be easy enough to support *all* C++11 extra declaration features at once. In most cases the lib has to simply parse the pp syntax and generate the C++11 native code under-nit.
BTW, I have not see any example using exception specifications using 'throws'. Does the library support them?
Yes, for example:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Thanks, I have not yet read this part.
Could you confirm? and if not, could you tell us if you have a plan to support them?
= Postconditions result =
"Postconditions can access the function return value by declaring a variable of type |auto| and assigning it to the |return| keyword (the variable name is arbitrary but |result| is often used)."
What prevent the library to the use of return instead of an auto variable
postcondition( // Postconditions. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... return == old_value )
This won't work if return is not the 1st token:
old_value == return 3 + return myfync(return) etc
because there's no way the preprocessor can skip the leading tokens given that they are unknown :( and they could contain symbols. I will clarify this point in the rationale.
OK. I understand.
instead of
postcondition( // Postconditions. auto result = return, // Result value. auto old_value = CONTRACT_OLDOF value, // Old value(s). value == old_value + 1, // Assertion(s)... result == old_value )
=Constant assertions =
I would expect that the old are always const so the following
postcondition( auto old_even = CONTRACT_OLDOF even, auto old_odd = CONTRACT_OLDOF odd, // `[old_]even` and `[old_]odd` all `const&` within assertions. const( even, old_even ) even == old_even + 2, const( odd, old_odd ) odd == old_odd + 2 )
old_... are const but you need to specify them in const( ... ) so they can be accessed by the constant-assertion boolean condition:
const( var1, var2, ... ) boolean-condition-using-var1-var2-...
Why?
Because constant-assertions are implemented using local functions which have such a limitation. Essentially, constant-assertions are local function's constant blocks:
http://www.boost.org/doc/libs/1_51_0/libs/local_function/doc/html/boost_loca... I'll document this rationale.
I understand now why all the used variables need to be declared. I don't think I will use it to prevent from constness errors. Note that reversing
I'd agree. Maybe you only use it when you need to be 100% sure about contract's const-correctness -- rarely -- but it's there for these rare cases. Most of the times having the object and the function arguments as const (automatically done by the lib) should be plenty enough to catch const-correctness violations.
the arguments in assertions/checks is a good practice:
old_odd + 2 == odd
Sure. In general assertions might call f(old_odd, odd) where f's arguments are non-const references but for easy checks like == the above is a good practice as usual (e.g., that's how I usually write if-conditions).
How this const local functions relates to c++11 lambda expressions?
They don't help because you cannot bind by constant-reference. If you bind by value, it's const but it requires a copy constructor :( (as we discussed in the local function review). Thanks, --Lorenzo

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." = C++03 limitations = It would be great if you add a section/table with all the limitations, as e.g. these ones * 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 :( = _BODY macros = Why do you need to make a difference between CONTRACT_FREE_BODYand CONTRACT_MEMBER_BODY while there is a single CONTRACT_FUNCTION? What if the user uses CONTRACT_FREE_BODYwhen it should use CONTRACT_MEMBER_BODY? It will not have the associated class invariants. 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|, |CONTRACT_DESTRUCTOR_BODY|, and |CONTRACT_MEMBER_BODY.| What do you think? = ( 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? = _TPL macros and performance = Could you give some figures of the gain of the change of introducing the _TPL macros? = Static assertions = What is the interest of disabling static assertion when |CONTRACT_CONFIG_NO_PRECONDITIONS|, |CONTRACT_CONFIG_NO_POSTCONDITIONS| are defined? = 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. Best, Vicente

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 : 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: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
= 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 declared.
= _BODY macros =
Why do you need to make a difference between CONTRACT_FREE_BODYand CONTRACT_MEMBER_BODY while there is a single CONTRACT_FUNCTION?
See note 32: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
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|, |CONTRACT_DESTRUCTOR_BODY|, and |CONTRACT_MEMBER_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: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
= ( 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 docs.
= _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 |CONTRACT_CONFIG_NO_PRECONDITIONS|, |CONTRACT_CONFIG_NO_POSTCONDITIONS| are 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. Thanks, --Lorenzo

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 : 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: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... I have read these notes. This seems to me a *hard* limitation and I would like you explain here deeply and broadly why, maybe someone could give you some ideas on alternatives.
= C++03 limitations =
It would be great if you add a section/table with all the limitations, as e.g. these ones Will do. Maybe you could already replay by completing the list below, and for each one if there is a possibility/plan to remove it.
* 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 declared. Maybe a native English could replay to this point.I'm not really sure my interpretation is correct. = _BODY macros =
Why do you need to make a difference between CONTRACT_FREE_BODYand CONTRACT_MEMBER_BODY while there is a single CONTRACT_FUNCTION? See note 32: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... This let me think that for uniformity it would be an alternative to have CONTACT_MEMBER and CONTRACT_FREE or maybe CONTACT_MEMBER_FUNCTION and CONTRACT_FREE_FUNCTION.
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...". This is not enough. The user would need to test her application using several combinations, which is not admissible.
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|, |CONTRACT_DESTRUCTOR_BODY|, and |CONTRACT_MEMBER_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: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... I don't see how this note respond to my point. Could you clarify, please?
= ( 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 docs. Do you plan to support it?
= _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. How many non-template functions are created for the non _TPL implementation?
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 |CONTRACT_CONFIG_NO_PRECONDITIONS|, |CONTRACT_CONFIG_NO_POSTCONDITIONS| are 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. Disabling preconditions/postconditions or invariants has a sense as these are run-time checks, but static assertions as checked at compile-time.
= 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.
As you are copying the return value, the user can not use move semantics, and the library need to take care of this explicitly. Do you plan to take care of move semantics before release (if accepted)? Best, Vicente

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 : 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:
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) }
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 :)
= C++03 limitations =
It would be great if you add a section/table with all the limitations, as e.g. these ones
Will do.
Maybe you could already replay by completing the list below, and for each one if there is a possibility/plan to remove it.
The list below should be complete.
* Function and array types cannot be directly used as function parameter types within the contract macros ...
Can't remove this limitation because C++ declaration syntax mixes types and names for these parameters :( void f ( int* (*fptr) ( int, int ), int* array[2][3] ) Names are within the types... instead of <type> <name>. The pp simply can't go into such token expressions and extract the names unless I add parenthesis to the expressions: CONTRACT_FUNCTION( void (f) ( (int*) ((*)fptr) ( int, int ), (int*) (array)[2][3] ) ) ... General grammar: Function parameters: (function-result-type) ([(*)|(&)]function-parameter-name) ( function-parameters ) Array parameters: (array-type) (array-parameter-name) [array-dimension]... IMO, that's a more complex syntax than using the typedef workaround.
* Each function parameter must always specify both its type and its name (parameter names can instead by omitted in usual C++ declarations).
This can be removed (just more pp code). Furthermore, if no name is specified, the type can but it does not have to be wrapped by extra parenthesis. I must do this if I extend the lib for concept definitions and I could do this in any case if reviewers asked for it.
* 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).
Removing this limitation will complicate the pp parsing code significantly (because I need to handle all the combinations, probably also increasing preprocessing-time) without adding any functionality. It can be done for sure but I've no plan to do this.
* Unfortunately, this library does not allow to specify contracts for unions.
I'm not sure... I could look into this if reviewers indicated it is important. Also unions changed in C++11... I don't remember how... This is planned for future work: http://sourceforge.net/apps/trac/contractpp/ticket/50
* Unfortunately, when member initializers are specified, the constructor body must be defined together with its declaration and contract
Maybe using C++11 delegating constructors? Currently, marked for future work: http://sourceforge.net/apps/trac/contractpp/ticket/51 But I'll send another email to discuss ideas and I could try to remove this limitation if reviewers indicated it's important.
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 declared.
Maybe a native English could replay to this point.I'm not really sure my interpretation is correct.
I'll double check the C++ standard anyway.
= _BODY macros =
Why do you need to make a difference between CONTRACT_FREE_BODYand CONTRACT_MEMBER_BODY while there is a single CONTRACT_FUNCTION?
See note 32:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
This let me think that for uniformity it would be an alternative to have CONTACT_MEMBER and CONTRACT_FREE or maybe CONTACT_MEMBER_FUNCTION and CONTRACT_FREE_FUNCTION.
I don't thinks so but it's largely a matter of personal taste... the BODY macros do something different from the FUNCTION macros (i.e.g, BODY = definition, FUNCTION = declaration) so IMO it's OK if the names are not symmetric. I like that the FUNCTION macro is smart enough to automatically distinguish between free and member function declarations.
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...".
This is not enough. The user would need to test her application using several combinations, which is not admissible.
Well, the user needs to use the correct macros as the docs say :) Ideally, I'd catch all syntax errors but I know I can't :(
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|, |CONTRACT_DESTRUCTOR_BODY|, and |CONTRACT_MEMBER_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:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
I don't see how this note respond to my point. Could you clarify, please?
This is possible: CONTRACT_MEMBER_BODY((natural<T, Default>),equal) In fact, this was the API of this macro in 0.4.0. I changed it (back) to: natural<T, Default>::CONTRACT_MEMBER_BODY(equal) In 0.4.1 because CONTRACT_MEMBER_BODY(equal) can be used if you want to derive a base class with contracts but without using the contract macros in programming the derived class (in this case the derived class has the exact same contracts as the base class). This is a nice feature because if I program a base class using contracts then other programmers can derive it and they are not forced to use contracts in programming the derived class. In other words, using contracts doesn't force neither the callers nor other programmers (namely the derived class programmers) to also use contracts. I think this feature is more important than the homogeneity between CONTRUCTOR/DESTRUCTRO/MEMBER BODY -- note that CONTRACTUOR/DESTRUCTOR and MEMBER/FREE have homogeneous interfaces, the mnemonic difference is between creation and functions instead than between members and free functions.
= ( 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 docs.
Do you plan to support it?
Sure, I can if reviewers ask for it. IMO, ( void ) is good enough (but that's a matter of personal taste).
= _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.
How many non-template functions are created for the non _TPL implementation?
Always 4 extra functions: _TPL: 4 extra functions which are templated only if the user function was a template. non-_TPL: 4 extra functions which are always templated (even if the user function was not a template). On a side note, it /might/ be possible to limit the number of extra functions to 2: http://sourceforge.net/apps/trac/contractpp/ticket/42
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 |CONTRACT_CONFIG_NO_PRECONDITIONS|, |CONTRACT_CONFIG_NO_POSTCONDITIONS| are 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.
Disabling preconditions/postconditions or invariants has a sense as these are run-time checks, but static assertions as checked at compile-time.
Yes, of course. But I was asking: CONTRACT_FUNCTION( template( typename T ) void (f) ( (T const&) x ) precondition( static_assert(sizeof(T) > sizeof(int), "big") ) // (1) postcondition( static_assert(2 * sizeof(T) > sizeof(long), "twice big") ) // (2) ) { static_assert(sizeof(T) > sizeof(int), "big"); // (3) ... // body static_assert(2 * sizeof(T) > sizeof(long), "twice big"); // (4) } What would be the difference between (1), (2), and even (3) and (4) if CONTRACT_CONFIG_NO_PRECONDITION/POSTCONDITION did not disable (1) and (2)? (I'm not really sure about this... I'm happy to discuss.)
= 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.
As you are copying the return value, the user can not use move semantics, and the library need to take care of this explicitly. Do you plan to take care of move semantics before release (if accepted)?
Sure if a reviewer ask for it ;) Thanks a lot! --Lorenzo

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 : 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:
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.
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.
= C++03 limitations =
It would be great if you add a section/table with all the limitations, as e.g. these ones Will do. Maybe you could already replay by completing the list below, and for each one if there is a possibility/plan to remove it. The list below should be complete.
* Function and array types cannot be directly used as function parameter types within the contract macros ... Can't remove this limitation because C++ declaration syntax mixes types and names for these parameters :(
void f ( int* (*fptr) ( int, int ), int* array[2][3] )
Names are within the types... instead of <type> <name>. The pp simply can't go into such token expressions and extract the names unless I add parenthesis to the expressions:
CONTRACT_FUNCTION( void (f) ( (int*) ((*)fptr) ( int, int ), (int*) (array)[2][3] ) ) ...
General grammar: Function parameters: (function-result-type) ([(*)|(&)]function-parameter-name) ( function-parameters ) Array parameters: (array-type) (array-parameter-name) [array-dimension]...
IMO, that's a more complex syntax than using the typedef workaround. I agree.
* Each function parameter must always specify both its type and its name (parameter names can instead by omitted in usual C++ declarations). This can be removed (just more pp code). Furthermore, if no name is specified, the type can but it does not have to be wrapped by extra parenthesis. I must do this if I extend the lib for concept definitions and I could do this in any case if reviewers asked for it. I can live with this limitation as soon as we don't get warnings when
Le 27/08/12 17:17, Lorenzo Caminiti a écrit : the parameter is not used.
* 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). Removing this limitation will complicate the pp parsing code significantly (because I need to handle all the combinations, probably also increasing preprocessing-time) without adding any functionality. It can be done for sure but I've no plan to do this.
I can live with this limitation.
* Unfortunately, this library does not allow to specify contracts for unions. I'm not sure... I could look into this if reviewers indicated it is important. Also unions changed in C++11... I don't remember how... This is planned for future work: http://sourceforge.net/apps/trac/contractpp/ticket/50 I can live with this limitation.
= _BODY macros =
Why do you need to make a difference between CONTRACT_FREE_BODYand CONTRACT_MEMBER_BODY while there is a single CONTRACT_FUNCTION? See note 32:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... This let me think that for uniformity it would be an alternative to have CONTACT_MEMBER and CONTRACT_FREE or maybe CONTACT_MEMBER_FUNCTION and CONTRACT_FREE_FUNCTION. I don't thinks so but it's largely a matter of personal taste... the BODY macros do something different from the FUNCTION macros (i.e.g, BODY = definition, FUNCTION = declaration) so IMO it's OK if the names are not symmetric. I like that the FUNCTION macro is smart enough to automatically distinguish between free and member function declarations.
You are right, it is a matter of taste.
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...". This is not enough. The user would need to test her application using several combinations, which is not admissible. Well, the user needs to use the correct macros as the docs say :) Ideally, I'd catch all syntax errors but I know I can't :(
I agree the library can not catch all syntax/semantic errors, but IMO the library can avoid this one, even if the consequences are not so important.
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|, |CONTRACT_DESTRUCTOR_BODY|, and |CONTRACT_MEMBER_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:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... I don't see how this note respond to my point. Could you clarify, please? This is possible:
CONTRACT_MEMBER_BODY((natural<T, Default>),equal)
In fact, this was the API of this macro in 0.4.0. I changed it (back) to:
natural<T, Default>::CONTRACT_MEMBER_BODY(equal)
In 0.4.1 because CONTRACT_MEMBER_BODY(equal) can be used if you want to derive a base class with contracts but without using the contract macros in programming the derived class (in this case the derived class has the exact same contracts as the base class). This is a nice feature because if I program a base class using contracts then other programmers can derive it and they are not forced to use contracts in programming the derived class. In other words, using contracts doesn't force neither the callers nor other programmers (namely the derived class programmers) to also use contracts.
Could you explain why the older form CONTRACT_MEMBER_BODY((natural<T, Default>),equal) can not be used for a derived class CONTRACT_MEMBER_BODY(DERIVED,equal)
I think this feature is more important than the homogeneity between CONTRUCTOR/DESTRUCTRO/MEMBER BODY -- note that CONTRACTUOR/DESTRUCTOR and MEMBER/FREE have homogeneous interfaces, the mnemonic difference is between creation and functions instead than between members and free functions. I must agree with you here.
= ( 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 docs. Do you plan to support it? Sure, I can if reviewers ask for it. IMO, ( void ) is good enough (but that's a matter of personal taste). The fact that this is a matter of taste let me think that the library should implement (if this is not too complex) it so that the user can write code according to her taste.
= _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. How many non-template functions are created for the non _TPL implementation? Always 4 extra functions: _TPL: 4 extra functions which are templated only if the user function was a template. non-_TPL: 4 extra functions which are always templated (even if the user function was not a template).
I'm not sure the fact the function are templates instead of inlined functions change a lot. But of course, it is up to you to provide a simpler interface.
On a side note, it /might/ be possible to limit the number of extra functions to 2: http://sourceforge.net/apps/trac/contractpp/ticket/42
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 |CONTRACT_CONFIG_NO_PRECONDITIONS|, |CONTRACT_CONFIG_NO_POSTCONDITIONS| are 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. Disabling preconditions/postconditions or invariants has a sense as these are run-time checks, but static assertions as checked at compile-time. Yes, of course. But I was asking:
CONTRACT_FUNCTION( template( typename T ) void (f) ( (T const&) x ) precondition( static_assert(sizeof(T) > sizeof(int), "big") ) // (1) postcondition( static_assert(2 * sizeof(T) > sizeof(long), "twice big") ) // (2) ) { static_assert(sizeof(T) > sizeof(int), "big"); // (3) ... // body static_assert(2 * sizeof(T) > sizeof(long), "twice big"); // (4) }
What would be the difference between (1), (2), and even (3) and (4) if CONTRACT_CONFIG_NO_PRECONDITION/POSTCONDITION did not disable (1) and (2)? (I'm not really sure about this... I'm happy to discuss.) My concern was, what could be the interest of introducing static assertions on the pre/post condition? Of course, if pre/post conditions are disabled, all the code included in (including static assertions) must be removed.
= 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.
As you are copying the return value, the user can not use move semantics, and the library need to take care of this explicitly. Do you plan to take care of move semantics before release (if accepted)? Sure if a reviewer ask for it ;) Do you mean if, for example, I request it on a formal review? ;-)
Best, Vicente

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 : 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:
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.
= C++03 limitations =
It would be great if you add a section/table with all the limitations, as e.g. these ones
Will do.
Maybe you could already replay by completing the list below, and for each one if there is a possibility/plan to remove it.
The list below should be complete.
* Function and array types cannot be directly used as function parameter types within the contract macros ...
Can't remove this limitation because C++ declaration syntax mixes types and names for these parameters :(
void f ( int* (*fptr) ( int, int ), int* array[2][3] )
Names are within the types... instead of <type> <name>. The pp simply can't go into such token expressions and extract the names unless I add parenthesis to the expressions:
CONTRACT_FUNCTION( void (f) ( (int*) ((*)fptr) ( int, int ), (int*) (array)[2][3] ) ) ...
General grammar: Function parameters: (function-result-type) ([(*)|(&)]function-parameter-name) ( function-parameters ) Array parameters: (array-type) (array-parameter-name) [array-dimension]...
IMO, that's a more complex syntax than using the typedef workaround.
I agree.
* Each function parameter must always specify both its type and its name (parameter names can instead by omitted in usual C++ declarations).
This can be removed (just more pp code). Furthermore, if no name is specified, the type can but it does not have to be wrapped by extra parenthesis. I must do this if I extend the lib for concept definitions and I could do this in any case if reviewers asked for it.
I can live with this limitation as soon as we don't get warnings when the parameter is not used.
I'm not sure about the warnings... but I'll just support no parameter names, it shouldn't be hard, it'll allow to avoid extra parenthesis around types when no name is used, and it's needed for concept definitions (if I'll ever get around implementing those). I entered a ticket for it: https://sourceforge.net/apps/trac/contractpp/ticket/63
* 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).
Removing this limitation will complicate the pp parsing code significantly (because I need to handle all the combinations, probably also increasing preprocessing-time) without adding any functionality. It can be done for sure but I've no plan to do this.
I can live with this limitation.
* Unfortunately, this library does not allow to specify contracts for unions.
I'm not sure... I could look into this if reviewers indicated it is important. Also unions changed in C++11... I don't remember how... This is planned for future work: http://sourceforge.net/apps/trac/contractpp/ticket/50
I can live with this limitation.
= _BODY macros =
Why do you need to make a difference between CONTRACT_FREE_BODYand CONTRACT_MEMBER_BODY while there is a single CONTRACT_FUNCTION?
See note 32:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
This let me think that for uniformity it would be an alternative to have CONTACT_MEMBER and CONTRACT_FREE or maybe CONTACT_MEMBER_FUNCTION and CONTRACT_FREE_FUNCTION.
I don't thinks so but it's largely a matter of personal taste... the BODY macros do something different from the FUNCTION macros (i.e.g, BODY = definition, FUNCTION = declaration) so IMO it's OK if the names are not symmetric. I like that the FUNCTION macro is smart enough to automatically distinguish between free and member function declarations.
You are right, it is a matter of taste.
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...".
This is not enough. The user would need to test her application using several combinations, which is not admissible.
Well, the user needs to use the correct macros as the docs say :) Ideally, I'd catch all syntax errors but I know I can't :(
I agree the library can not catch all syntax/semantic errors, but IMO the library can avoid this one, even if the consequences are not so important.
I'm not sure if I can catch this error but if I can, I will. I've added a ticket for it: https://sourceforge.net/apps/trac/contractpp/ticket/64
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|, |CONTRACT_DESTRUCTOR_BODY|, and |CONTRACT_MEMBER_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:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
I don't see how this note respond to my point. Could you clarify, please?
This is possible:
CONTRACT_MEMBER_BODY((natural<T, Default>),equal)
In fact, this was the API of this macro in 0.4.0. I changed it (back) to:
natural<T, Default>::CONTRACT_MEMBER_BODY(equal)
In 0.4.1 because CONTRACT_MEMBER_BODY(equal) can be used if you want to derive a base class with contracts but without using the contract macros in programming the derived class (in this case the derived class has the exact same contracts as the base class). This is a nice feature because if I program a base class using contracts then other programmers can derive it and they are not forced to use contracts in programming the derived class. In other words, using contracts doesn't force neither the callers nor other programmers (namely the derived class programmers) to also use contracts.
Could you explain why the older form
CONTRACT_MEMBER_BODY((natural<T, Default>),equal)
can not be used for a derived class
CONTRACT_MEMBER_BODY(DERIVED,equal)
Take a look at this example: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... This can be done (note no CONTRACT_CLASS/FUNCTION macros so usual C++ declaration syntax): // base declared with contracts... class deriv : public base { public: virtual void CONTRACT_MEMBER_BODY(f) ( void ) { std::clog << "deriv::f::body" << std::endl; } }; But this cannot be done: class deriv : public base { public: virtual void CONTRACT_MEMBER_BODY(deriv, f) ( void ) { std::clog << "deriv::f::body" << std::endl; } }; Because at some point, BODY(deriv, f) has to expand to deriv::contractXbodyXf (or just deriv::f is member function contracts are disabled when no pre, no post, and no class inv) and you cannot prefix a member function with the class name within the class declaration itself (plus it'd be redundant to repeat deriv in the BODY macro within deriv's declaration).
I think this feature is more important than the homogeneity between CONTRUCTOR/DESTRUCTRO/MEMBER BODY -- note that CONTRACTUOR/DESTRUCTOR and MEMBER/FREE have homogeneous interfaces, the mnemonic difference is between creation and functions instead than between members and free functions.
I must agree with you here.
= ( 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 docs.
Do you plan to support it?
Sure, I can if reviewers ask for it. IMO, ( void ) is good enough (but that's a matter of personal taste).
The fact that this is a matter of taste let me think that the library should implement (if this is not too complex) it so that the user can write code according to her taste.
Again, if reviewers ask, I'll support. Note that the fact that a major compiler like MSVC messes this up will inevitably make the ( ) syntax useless for a large number of users :( even if I endure the effort and point to support it and fully test it.
= _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.
How many non-template functions are created for the non _TPL implementation?
Always 4 extra functions: _TPL: 4 extra functions which are templated only if the user function was a template. non-_TPL: 4 extra functions which are always templated (even if the user function was not a template).
I'm not sure the fact the function are templates instead of inlined functions change a lot. But of course, it is up to you to provide a simpler interface.
On a side note, it /might/ be possible to limit the number of extra functions to 2: http://sourceforge.net/apps/trac/contractpp/ticket/42
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 |CONTRACT_CONFIG_NO_PRECONDITIONS|, |CONTRACT_CONFIG_NO_POSTCONDITIONS| are 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.
Disabling preconditions/postconditions or invariants has a sense as these are run-time checks, but static assertions as checked at compile-time.
Yes, of course. But I was asking:
CONTRACT_FUNCTION( template( typename T ) void (f) ( (T const&) x ) precondition( static_assert(sizeof(T) > sizeof(int), "big") ) // (1) postcondition( static_assert(2 * sizeof(T) > sizeof(long), "twice big") ) // (2) ) { static_assert(sizeof(T) > sizeof(int), "big"); // (3) ... // body static_assert(2 * sizeof(T) > sizeof(long), "twice big"); // (4) }
What would be the difference between (1), (2), and even (3) and (4) if CONTRACT_CONFIG_NO_PRECONDITION/POSTCONDITION did not disable (1) and (2)? (I'm not really sure about this... I'm happy to discuss.)
My concern was, what could be the interest of introducing static assertions on the pre/post condition? Of course, if pre/post conditions are disabled, all the code included in (including static assertions) must be removed.
OK, I understand. My answer is "I'm not sure...": In pre/post/inv you can write assertions and I wanted to support static assertions so if some of these correctness conditions can be checked at compile-time, they will. I think if contracts were added to C++1x, we'd expect to naturally be able to use static_assert in the pre/post/inv. Older rev of N1962 supported static assertions and N1962 does not because static_assert was added to C++11: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1866.html#static-as... However, I don't have a use case that shows static assertions are critical for contract programming (only a few examples in the Example section, search for static_assert). On the contrary, most of contract assertions you want/need to write can only be checked at run-time.
= 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.
As you are copying the return value, the user can not use move semantics, and the library need to take care of this explicitly. Do you plan to take care of move semantics before release (if accepted)?
Sure if a reviewer ask for it ;)
Do you mean if, for example, I request it on a formal review? ;-)
Yes ;) Thanks. --Lorenzo

Le 27/08/12 22:05, Lorenzo Caminiti a écrit :
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 :
Could you explain why the older form
CONTRACT_MEMBER_BODY((natural<T, Default>),equal)
can not be used for a derived class
CONTRACT_MEMBER_BODY(DERIVED,equal) Take a look at this example: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
This can be done (note no CONTRACT_CLASS/FUNCTION macros so usual C++ declaration syntax):
// base declared with contracts...
class deriv : public base { public: virtual void CONTRACT_MEMBER_BODY(f) ( void ) { std::clog << "deriv::f::body" << std::endl; } };
But this cannot be done:
class deriv : public base { public: virtual void CONTRACT_MEMBER_BODY(deriv, f) ( void ) { std::clog << "deriv::f::body" << std::endl; } };
Because at some point, BODY(deriv, f) has to expand to deriv::contractXbodyXf (or just deriv::f is member function contracts are disabled when no pre, no post, and no class inv) and you cannot prefix a member function with the class name within the class declaration itself (plus it'd be redundant to repeat deriv in the BODY macro within deriv's declaration).
= Static assertions =
What is the interest of disabling static assertion when |CONTRACT_CONFIG_NO_PRECONDITIONS|, |CONTRACT_CONFIG_NO_POSTCONDITIONS| are 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. Disabling preconditions/postconditions or invariants has a sense as these are run-time checks, but static assertions as checked at compile-time. Yes, of course. But I was asking:
CONTRACT_FUNCTION( template( typename T ) void (f) ( (T const&) x ) precondition( static_assert(sizeof(T) > sizeof(int), "big") ) // (1) postcondition( static_assert(2 * sizeof(T) > sizeof(long), "twice big") ) // (2) ) { static_assert(sizeof(T) > sizeof(int), "big"); // (3) ... // body static_assert(2 * sizeof(T) > sizeof(long), "twice big"); // (4) }
What would be the difference between (1), (2), and even (3) and (4) if CONTRACT_CONFIG_NO_PRECONDITION/POSTCONDITION did not disable (1) and (2)? (I'm not really sure about this... I'm happy to discuss.) My concern was, what could be the interest of introducing static assertions on the pre/post condition? Of course, if pre/post conditions are disabled, all the code included in (including static assertions) must be removed. OK, I understand. My answer is "I'm not sure...": In pre/post/inv you can write assertions and I wanted to support static assertions so if some of these correctness conditions can be checked at compile-time, they will. I think if contracts were added to C++1x, we'd expect to naturally be able to use static_assert in the pre/post/inv. Older rev of N1962 supported static assertions and N1962 does not because static_assert was added to C++11: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1866.html#static-as... After reading this, I understand better that some static assertions could be part of a contract. I will expect however these assertions are
I'm not sure the suffix _BODY is the adequate here. What do you think of CONTRACT_MEMBER_NAME class deriv : public base { public: virtual void CONTRACT_MEMBER_NAME(f) ( void ) { std::clog << "deriv::f::body" << std::endl; } }; And let CONTRACT_MEMBER_BODY to follow the pattern of CONTRACT_CONSTRUCTOR_BODY and CONTRACT_DESTRUCTOR_BODY? 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); } maintained independently of whether CONTRACT_CONFIG_NO_PRECONDITIONS|, |CONTRACT_CONFIG_NO_POSTCONDITIONS are defined or not. If tis is not the case, I'm sure I will move the static assertions to the body, but in this case they will not be part of the declared contract which is odd. = doxygen = BTW, have you tried to generate contract documentation using doxygen? = enable-if = Have you an example of the use of enable_if and contracts in the documentation? Best, Vicente

Le 27/08/12 23:15, Vicente J. Botet Escriba a écrit :
= doxygen =
BTW, have you tried to generate contract documentation using doxygen?
= enable-if =
Have you an example of the use of enable_if and contracts in the documentation?
Hi Lorenzo, could you comment these two points? Best, Vicente

On Sep 1, 2012 9:56 AM, "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr> wrote:
Le 27/08/12 23:15, Vicente J. Botet Escriba a écrit :
= doxygen =
BTW, have you tried to generate contract documentation using doxygen?
Doxygen's preprocessor is too simple and it cannot correctly expand the macros. To generate Doxygen docs of code that contains the contract macros, you'd have to expand it before running Doxygen using you compiler -E or something like Wave so to feed Doxygen the code with the macros already expanded. You'd have to expand with all contracts disabled so Doxygen will see your normal code and generates docs for it. A different question (I'm not sure which one you intended to ask) is if my lib macros can automatically generate Doxygen's @pre, @post, and @inv tags (they are named something like that). An older rev used to do that--see release 0.3.469 in the Release Notes section (idea taken from [Tadin04], see Bibliography section and Features at bottom of Contract Programming Overview section). However, the Doxygen docs simply repeated the assertion code in the docs so it was more or less like looking at the contract code from the declarations (without the function definition code). Such automatically generated docs where of little value then the macros got too complex for the Doxygen pp anyway so this feature was abandoned.
= enable-if =
Have you an example of the use of enable_if and contracts in the documentation?
This should work as usual but I just realized I don't have an example for it. I'll test it and add an enable_if example.
Hi Lorenzo,
could you comment these two points?
My apologies I forgot to reply on these tow points. All, it's my honest intention to satisfactorly reply to all comments you make (otherwise, why would I ask a review?) If I forget to reply to an item or my reply is not satisfactory, please poit that out to me as Vicente just did. Thanks! --Lorenzo

Le 01/09/12 20:15, Lorenzo Caminiti a écrit :
On Sep 1, 2012 9:56 AM, "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr> wrote:
Le 27/08/12 23:15, Vicente J. Botet Escriba a écrit :
= doxygen =
BTW, have you tried to generate contract documentation using doxygen? Doxygen's preprocessor is too simple and it cannot correctly expand the macros. To generate Doxygen docs of code that contains the contract macros, you'd have to expand it before running Doxygen using you compiler -E or something like Wave so to feed Doxygen the code with the macros already expanded. You'd have to expand with all contracts disabled so Doxygen will see your normal code and generates docs for it. NO This was not what I was expecting for doxygen ;-)
A different question (I'm not sure which one you intended to ask) is if my lib macros can automatically generate Doxygen's @pre, @post, and @inv tags (they are named something like that).
Yes, something like this is what I was requesting. I don't care about whether the macros generate doxygen tags as @pre,@post and @inv. What I want is an automatic generation for quickbook documents using doxygen.
An older rev used to do that--see release 0.3.469 in the Release Notes section (idea taken from [Tadin04], see Bibliography section and Features at bottom of Contract Programming Overview section). However, the Doxygen docs simply repeated the assertion code in the docs so it was more or less like looking at the contract code from the declarations (without the function definition code). Such automatically generated docs where of little value then the macros got too complex for the Doxygen pp anyway so this feature was abandoned.
Are you saying that the user can look at the code as it describes clearly the pre/post/inv and the documentation is not needed anymore? Does you mean that people using your Contract library, and wanting an hypertext documentation, will need to rewrite the pre/post/inv documentation by hand if they want the information is on their hypertext docs?
= enable-if =
Have you an example of the use of enable_if and contracts in the documentation?
This should work as usual but I just realized I don't have an example for it. I'll test it and add an enable_if example.
I was wondering if the library should not use enable_if to emulate C++ proposed Concepts, as e.g. it seems Boost.Generic does. More I think on how you are emulating C++ concepts, more I think that the emulation doesn't corresponds to what a C++Concept user could expect. The use of Boost.ConceptCheck doesn't seems to match the C++11 proposed Concept semantics. I'm not saying that Boost.ConceptCheck is not useful, but the semantic is different. Best, Vicente

On Sun, Sep 2, 2012 at 1:02 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 01/09/12 20:15, Lorenzo Caminiti a écrit :
On Sep 1, 2012 9:56 AM, "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr> wrote:
Le 27/08/12 23:15, Vicente J. Botet Escriba a écrit :
= doxygen =
BTW, have you tried to generate contract documentation using doxygen?
Doxygen's preprocessor is too simple and it cannot correctly expand the macros. To generate Doxygen docs of code that contains the contract macros, you'd have to expand it before running Doxygen using you compiler -E or something like Wave so to feed Doxygen the code with the macros already expanded. You'd have to expand with all contracts disabled so Doxygen will see your normal code and generates docs for it.
NO This was not what I was expecting for doxygen ;-)
A different question (I'm not sure which one you intended to ask) is if my lib macros can automatically generate Doxygen's @pre, @post, and @inv tags (they are named something like that).
Yes, something like this is what I was requesting. I don't care about whether the macros generate doxygen tags as @pre,@post and @inv. What I want is an automatic generation for quickbook documents using doxygen.
An older rev used to do that--see release 0.3.469 in the Release Notes section (idea taken from [Tadin04], see Bibliography section and Features at bottom of Contract Programming Overview section). However, the Doxygen docs simply repeated the assertion code in the docs so it was more or less like looking at the contract code from the declarations (without the function definition code). Such automatically generated docs where of little value then the macros got too complex for the Doxygen pp anyway so this feature was abandoned.
Are you saying that the user can look at the code as it describes clearly the pre/post/inv and the documentation is not needed anymore? Does you mean that people using your Contract library, and wanting an hypertext documentation, will need to rewrite the pre/post/inv documentation by hand if they want the information is on their hypertext docs?
Wow, I can't believe I still have this code :) but here's an example of the Doxygen docs generated using the older library rev: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... Generated from this code: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... I am saying that if you look at the Precondition/Postcondition/Invariant sections from the Doxygen link above they merely repeat the assertion code from the contracts you can read in the code itself. Therefore, this feature wasn't very useful to begin with then the macros became too complex for the Doxygen pp to expand them so this feature was removed. Is this the type of feature you are talking about? If not, could you provide an example of the code and ideal Doxygen docs generated? (Of course, you can write everything in just text format but just so I can see what would ideally be in the code and then in the automatically generated docs.)
= enable-if =
Have you an example of the use of enable_if and contracts in the
documentation?
This should work as usual but I just realized I don't have an example for it. I'll test it and add an enable_if example.
I was wondering if the library should not use enable_if to emulate C++ proposed Concepts, as e.g. it seems Boost.Generic does. More I think on how you are emulating C++ concepts, more I think that the emulation doesn't corresponds to what a C++Concept user could expect. The use of Boost.ConceptCheck doesn't seems to match the C++11 proposed Concept semantics. I'm not saying that Boost.ConceptCheck is not useful, but the semantic is different.
I agree. However, I think this is more along the line of extending the lib to support concept definitions: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... Note that at the (very) end I could allow a few things all together in the requires statement: 1. Boost.ConceptCheck for backward compatibility (current). 2. static_assert (if we decide that using static assertions in just the concept declarations is not enough). 3. Boost.Generic-like concepts defined and checked using C++11 expression SFINAE (future). HTH, --Lorenzo

Le 02/09/12 22:33, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 1:02 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 01/09/12 20:15, Lorenzo Caminiti a écrit :
On Sep 1, 2012 9:56 AM, "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr> wrote:
Le 27/08/12 23:15, Vicente J. Botet Escriba a écrit :
= doxygen =
BTW, have you tried to generate contract documentation using doxygen? Doxygen's preprocessor is too simple and it cannot correctly expand the macros. To generate Doxygen docs of code that contains the contract macros, you'd have to expand it before running Doxygen using you compiler -E or something like Wave so to feed Doxygen the code with the macros already expanded. You'd have to expand with all contracts disabled so Doxygen will see your normal code and generates docs for it. NO This was not what I was expecting for doxygen ;-)
A different question (I'm not sure which one you intended to ask) is if my lib macros can automatically generate Doxygen's @pre, @post, and @inv tags (they are named something like that).
Yes, something like this is what I was requesting. I don't care about whether the macros generate doxygen tags as @pre,@post and @inv. What I want is an automatic generation for quickbook documents using doxygen.
An older rev used to do that--see release 0.3.469 in the Release Notes section (idea taken from [Tadin04], see Bibliography section and Features at bottom of Contract Programming Overview section). However, the Doxygen docs simply repeated the assertion code in the docs so it was more or less like looking at the contract code from the declarations (without the function definition code). Such automatically generated docs where of little value then the macros got too complex for the Doxygen pp anyway so this feature was abandoned.
Are you saying that the user can look at the code as it describes clearly the pre/post/inv and the documentation is not needed anymore? Does you mean that people using your Contract library, and wanting an hypertext documentation, will need to rewrite the pre/post/inv documentation by hand if they want the information is on their hypertext docs? Wow, I can't believe I still have this code :) but here's an example of the Doxygen docs generated using the older library rev: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Generated from this code: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_... Yeah, this is really great.
I am saying that if you look at the Precondition/Postcondition/Invariant sections from the Doxygen link above they merely repeat the assertion code from the contracts you can read in the code itself. Therefore, this feature wasn't very useful to begin with then the macros became too complex for the Doxygen pp to expand them so this feature was removed.
Is this the type of feature you are talking about? If not, could you provide an example of the code and ideal Doxygen docs generated? (Of course, you can write everything in just text format but just so I can see what would ideally be in the code and then in the automatically generated docs.)
Yes this is what I was looking for. It will yet better if *Precondition: *{ index >= 0 && index <self.size()/* "index in range" */; } could become *Precondition: *index in range : index >= 0 && index <self.size()
= enable-if =
Have you an example of the use of enable_if and contracts in the documentation?
This should work as usual but I just realized I don't have an example for it. I'll test it and add an enable_if example.
I was wondering if the library should not use enable_if to emulate C++ proposed Concepts, as e.g. it seems Boost.Generic does. More I think on how you are emulating C++ concepts, more I think that the emulation doesn't corresponds to what a C++Concept user could expect. The use of Boost.ConceptCheck doesn't seems to match the C++11 proposed Concept semantics. I'm not saying that Boost.ConceptCheck is not useful, but the semantic is different. I agree. However, I think this is more along the line of extending the lib to support concept definitions: http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Note that at the (very) end I could allow a few things all together in the requires statement: 1. Boost.ConceptCheck for backward compatibility (current). 2. static_assert (if we decide that using static assertions in just the concept declarations is not enough). 3. Boost.Generic-like concepts defined and checked using C++11 expression SFINAE (future).
I think that this part (Concepts and the require clause) of the library is not enough mature and in order to avoid breaking changes in the future it should be removed now and added just once you have a more sound solution. Best, Vicente

On Sun, Sep 2, 2012 at 2:25 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 02/09/12 22:33, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 1:02 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 01/09/12 20:15, Lorenzo Caminiti a écrit :
On Sep 1, 2012 9:56 AM, "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr> wrote:
Le 27/08/12 23:15, Vicente J. Botet Escriba a écrit :
= doxygen =
BTW, have you tried to generate contract documentation using doxygen?
Doxygen's preprocessor is too simple and it cannot correctly expand the macros. To generate Doxygen docs of code that contains the contract macros, you'd have to expand it before running Doxygen using you compiler -E or something like Wave so to feed Doxygen the code with the macros already expanded. You'd have to expand with all contracts disabled so Doxygen will see your normal code and generates docs for it.
NO This was not what I was expecting for doxygen ;-)
A different question (I'm not sure which one you intended to ask) is if my lib macros can automatically generate Doxygen's @pre, @post, and @inv tags (they are named something like that).
Yes, something like this is what I was requesting. I don't care about whether the macros generate doxygen tags as @pre,@post and @inv. What I want is an automatic generation for quickbook documents using doxygen.
An older rev used to do that--see release 0.3.469 in the Release Notes section (idea taken from [Tadin04], see Bibliography section and Features at bottom of Contract Programming Overview section). However, the Doxygen docs simply repeated the assertion code in the docs so it was more or less like looking at the contract code from the declarations (without the function definition code). Such automatically generated docs where of little value then the macros got too complex for the Doxygen pp anyway so this feature was abandoned.
Are you saying that the user can look at the code as it describes clearly the pre/post/inv and the documentation is not needed anymore? Does you mean that people using your Contract library, and wanting an hypertext documentation, will need to rewrite the pre/post/inv documentation by hand if they want the information is on their hypertext docs?
Wow, I can't believe I still have this code :) but here's an example of the Doxygen docs generated using the older library rev:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Generated from this code:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Yeah, this is really great.
I am saying that if you look at the Precondition/Postcondition/Invariant sections from the Doxygen link above they merely repeat the assertion code from the contracts you can read in the code itself. Therefore, this feature wasn't very useful to begin with then the macros became too complex for the Doxygen pp to expand them so this feature was removed.
Is this the type of feature you are talking about? If not, could you provide an example of the code and ideal Doxygen docs generated? (Of course, you can write everything in just text format but just so I can see what would ideally be in the code and then in the automatically generated docs.)
Yes this is what I was looking for. It will yet better if
*Precondition: *{ index >= 0 && index <self.size()/* "index in range" */; }
could become
*Precondition: *index in range : index >= 0 && index <self.size()
I don't think this last part can be done. In any case, we'd need a more compliant Doxygen pp in order to support any of this... For example, just try to #define macros to disable all contract in the Doxyfile and then feed the code to Doxygen. In theory it should work (because without contracts you just get plain C++03 declarations out of the macro, essentially zero extra code) but Doxygen pp gets confused already :(
= enable-if =
Have you an example of the use of enable_if and contracts in the
documentation?
This should work as usual but I just realized I don't have an example for it. I'll test it and add an enable_if example.
I was wondering if the library should not use enable_if to emulate C++ proposed Concepts, as e.g. it seems Boost.Generic does. More I think on how you are emulating C++ concepts, more I think that the emulation doesn't corresponds to what a C++Concept user could expect. The use of Boost.ConceptCheck doesn't seems to match the C++11 proposed Concept semantics. I'm not saying that Boost.ConceptCheck is not useful, but the semantic is different.
I agree. However, I think this is more along the line of extending the lib to support concept definitions:
http://contractpp.svn.sourceforge.net/viewvc/contractpp/releases/contractpp_...
Note that at the (very) end I could allow a few things all together in the requires statement: 1. Boost.ConceptCheck for backward compatibility (current). 2. static_assert (if we decide that using static assertions in just the concept declarations is not enough). 3. Boost.Generic-like concepts defined and checked using C++11 expression SFINAE (future).
I think that this part (Concepts and the require clause) of the library is not enough mature and in order to avoid breaking changes in the future it should be removed now and added just once you have a more sound solution.
For now it's an only a way to interface with Boost.ConceptCheck. The rest are future ideas (nothing is "half-implemented"). We started to discuss static_assert and I'm happy to consider it... However, 3 will require a lot of work (especially because there's no Boost.Generic code to be found anywhere) and that's definitely future for a lib that deals with contracts and not concepts after all. However, I personally see no harm in leaving requires as is now so to check Boost.ConceptCheck concepts. Thanks, --Lorenzo

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
participants (2)
-
Lorenzo Caminiti
-
Vicente J. Botet Escriba