
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