
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