
Hi, here is my short review. My vote is YES subject to these condition. * Removal of the Concepts part. The use of Boost.ConceptCheck to emulate C++ concepts proposal is in my opinion erroneous. Boost.Concept.Check is used to assert the actual parameter satisfy statically the concept conditions, while if I'm not wrong the C++ Concepts proposal use the requires clause to state the conditions of a possible instantiations. Using the same grammar with different semantics is confusing. In a last resort, if this feature is preserved, the requires keyword must be changed by another one. * static assertions are removed from the pre/post conditions. They can be moved to a specific "static assertions" section at the same level than the requires clause. This section could also include the concept check included now in the requires clause. * The library extends the EDSL to use directly C++11 features, in particular move semantics. Now that since the C++11 standard is released, more and more people are using C++11 specific features. I, in particular, will not use Contract if I can not make use of C++11 features provided by the compiler. * The contract broken handlers are noexcept, so that adding contracts don't change the original prototype. === STANDARD REVIEW QUESTIONS === * What is your evaluation of the design? While Lorenzo has show that using the preprocessor we can define a EDSL that is close to the native syntax (besides the parentheses stuff), the resulting interface is *closed* and interacts badly with c++ features not taken in account by the EDSL. I'm guessing that the user can not extend this EDSL without modifying the library. This is also the case of other libraries that make use of the pre-procesor to define a EDSL as Boost.Parameters or Toward Boost.Generics. It will be great if the user can extend the EDSL, but I suppose this could be very hard, if not impossible. I understand that Lorenzo is trying to reduce the preprocessor time using whatever is needed, but making the interface more complex would not help to improve the usability. I'm not sure the _TPL macros are really needed and whether the resulting code could perform better or not. * What is your evaluation of the implementation? I've not look inside. * What is your evaluation of the documentation? Very good. I would appreciate if the documentation includes a sections showing what is behind the scenes, what is generated by these macros. 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 theGrammar 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 * What is your evaluation of the potential usefulness of the library? I don't think the library could be used in a industrial context. The domain of this preprocessor EDSL is too large (C++ declarations + contracts + named parameters + concepts) and we will need to expand it yet to be useful (c++11, compiler specifics, ...). While the syntax is quite close to C++ syntax the library intends to emulate, the compiler errors will be quite unreadables. * Did you try to use the library? With what compiler? Did you have any problems? No. * How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? I have not do a in-depth study. I has been concentrated inspecting the usability of the library and trying to identify the limitations it could introduce. * Are you knowledgeable about the problem domain? Yes, from a theoretical point of view. I have never used contract programming in real world projects. Best, Vicente

On Sun, Sep 2, 2012 at 2:39 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Hi,
here is my short review.
My vote is YES subject to these condition.
Thanks a lot for the review.
* Removal of the Concepts part. The use of Boost.ConceptCheck to emulate C++ concepts proposal is in my opinion erroneous. Boost.Concept.Check is used to assert the actual parameter satisfy statically the concept conditions, while if I'm not wrong the C++ Concepts proposal use the requires clause to state the conditions of a possible instantiations. Using the same grammar with different semantics is confusing. In a last resort, if this feature is preserved, the requires keyword must be changed by another one.
If that were to be the final decision, I'll remove the interface to Boost.ConceptCheck or I can use any (alphanumeric) mane rather than requires (e.g., where). However, I can use the requires clausule to do multiple things: 1. Check concepts defined using Boost.ConceptCheck (current, I'd leave it as is). 2. Check static_assert (under consideration, to be moved here from within pre/post/inv). 3. Check Boost.Generic-like concepts implemented using C++11 expression SFINAE (for future... this will be *a lot* of work...). I should be able to support of all those because I can distinguish 2 using the pp (starts with static_assert) and I can distinguish between 1 and 2 using the compiler for example using a (hidden) tagging base class to all concepts defined for 3. IMO, I'd stick with requires, leave 1 as is, maybe add 2 for now, and consider 3 for future.
* static assertions are removed from the pre/post conditions. They can be moved to a specific "static assertions" section at the same level than the requires clause. This section could also include the concept check included now in the requires clause.
OK (but I'd personally bundle all into requires).
* The library extends the EDSL to use directly C++11 features, in particular move semantics. Now that since the C++11 standard is released, more and more people are using C++11 specific features. I, in particular, will not use Contract if I can not make use of C++11 features provided by the compiler.
I'd prefer to add C++11 in future releases because the lib is usable as is for C++03 and adding the C++11 features will take time but it won't break the interface. Of course, I'll comply with whatever the final decision is.
* The contract broken handlers are noexcept, so that adding contracts don't change the original prototype.
They will be when C++11 support is added (again, I'd prefer later but I'm OK otherwise even if that will delay a possible release).
=== STANDARD REVIEW QUESTIONS ===
* What is your evaluation of the design?
While Lorenzo has show that using the preprocessor we can define a EDSL that is close to the native syntax (besides the parentheses stuff), the resulting interface is *closed* and interacts badly with c++ features not taken in account by the EDSL. I'm guessing that the user can not extend this EDSL without modifying the library.
Correct.
This is also the case of other libraries that make use of the pre-procesor to define a EDSL as Boost.Parameters or Toward Boost.Generics.
It will be great if the user can extend the EDSL, but I suppose this could be very hard, if not impossible.
I'm not even sure where to start to implement something like that... the lib is already complex the way it is... let alone if it supported some sort of IDL... I guess I'll start by thinking about it in my casual time now that you have raised the question :)
I understand that Lorenzo is trying to reduce the preprocessor time using whatever is needed, but making the interface more complex would not help to improve the usability. I'm not sure the _TPL macros are really needed and whether the resulting code could perform better or not.
To give you a definitive answer, I should really provide compile-times with and without _TPL. That's not trivial but I'll add a ticket to try to do that at some point. On the positive side, having the _TPL now and removing them later will not break backward compatibility.
* What is your evaluation of the implementation?
I've not look inside.
* What is your evaluation of the documentation? Very good.
I would appreciate if the documentation includes a sections showing what is behind the scenes, what is generated by these macros.
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 ...
This will be removed (at the cost of more complex syntax than the typedef but sometimes needed for deduced function template parameters).
* Each function parameter must always specify both its type and its name (parameter names can instead by omitted in usual C++ declarations).
This will be removed.
* All tokens must be specified in the fixed order listed in theGrammar 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
Will do.
* What is your evaluation of the potential usefulness of the library?
I don't think the library could be used in a industrial context.
The domain of this preprocessor EDSL is too large (C++ declarations +
Yep, even if you just leave at that "C++ declarations" the domain is huge (likely it doesn't trickle into the definitions...).
contracts + named parameters + concepts) and we will need to expand it yet to be useful (c++11, compiler specifics, ...). While the syntax is quite close to C++ syntax the library intends to emulate, the compiler errors will be quite unreadables.
* Did you try to use the library? With what compiler? Did you have any problems?
No. * How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? I have not do a in-depth study. I has been concentrated inspecting the usability of the library and trying to identify the limitations it could introduce.
* Are you knowledgeable about the problem domain?
Yes, from a theoretical point of view. I have never used contract programming in real world projects.
Thanks :) --Lorenzo

On Sun, Sep 2, 2012 at 2:39 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Hi,
here is my short review.
My vote is YES subject to these condition. Thanks a lot for the review.
* Removal of the Concepts part. The use of Boost.ConceptCheck to emulate C++ concepts proposal is in my opinion erroneous. Boost.Concept.Check is used to assert the actual parameter satisfy statically the concept conditions, while if I'm not wrong the C++ Concepts proposal use the requires clause to state the conditions of a possible instantiations. Using the same grammar with different semantics is confusing. In a last resort, if this feature is preserved, the requires keyword must be changed by another one. If that were to be the final decision, I'll remove the interface to Boost.ConceptCheck or I can use any (alphanumeric) mane rather than requires (e.g., where).
However, I can use the requires clausule to do multiple things: 1. Check concepts defined using Boost.ConceptCheck (current, I'd leave it as is). 2. Check static_assert (under consideration, to be moved here from within pre/post/inv). 3. Check Boost.Generic-like concepts implemented using C++11 expression SFINAE (for future... this will be *a lot* of work...). I should be able to support of all those because I can distinguish 2 using the pp (starts with static_assert) I will really prefer the static_assert goes outside requires, e.g. in a new *check* clause. This clause could also contain the ConceptCheck
and I can distinguish between 1 and 2 using the compiler for example using a (hidden) tagging base class to all concepts defined for 3. I'm not sure this distinction is possible. For function templates, the requires part associated to ConceptCheck should be included in the function definition, while the one associated to enable_if/SFINAE c++
Le 03/09/12 00:14, Lorenzo Caminiti a écrit : part. In this way it is clear that the requires part will disable the instantiation if not satisfied, and the check part will report a compile-time error if not satisfied. proposal concepts emulation should be part of the C++ declaration. For template classes, ConceptCheck goes to the members part, while Concepts goes to the template parameter part. As you can see the semantics are different, so a specific keyword would help to identify the difference.
IMO, I'd stick with requires, leave 1 as is, maybe add 2 for now, and consider 3 for future.
* static assertions are removed from the pre/post conditions. They can be moved to a specific "static assertions" section at the same level than the requires clause. This section could also include the concept check included now in the requires clause. OK (but I'd personally bundle all into requires).
* The library extends the EDSL to use directly C++11 features, in particular move semantics. Now that since the C++11 standard is released, more and more people are using C++11 specific features. I, in particular, will not use Contract if I can not make use of C++11 features provided by the compiler. I'd prefer to add C++11 in future releases because the lib is usable as is for C++03 and adding the C++11 features will take time but it won't break the interface. Of course, I'll comply with whatever the final decision is.
* The contract broken handlers are noexcept, so that adding contracts don't change the original prototype. They will be when C++11 support is added (again, I'd prefer later but I'm OK otherwise even if that will delay a possible release).
If you are allowed to release without C++11 support, it will be great if the documentation states clearly that the contract broken handlers can not throw. Otherwise, when moving to C++11, the C++03 usage will be broken. Even if you don't take care of C++11 features for the functions declaration, you could request that the contract broken handlers are noexcept using the Boost macro BOOST_NOEXCEPT, which is empty in C++03. Best, Vicente

On Sun, Sep 2, 2012 at 11:14 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 03/09/12 00:14, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 2:39 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Hi,
here is my short review.
My vote is YES subject to these condition.
Thanks a lot for the review.
* Removal of the Concepts part. The use of Boost.ConceptCheck to emulate C++ concepts proposal is in my opinion erroneous. Boost.Concept.Check is used to assert the actual parameter satisfy statically the concept conditions, while if I'm not wrong the C++ Concepts proposal use the requires clause to state the conditions of a possible instantiations. Using the same grammar with different semantics is confusing. In a last resort, if this feature is preserved, the requires keyword must be changed by another one.
If that were to be the final decision, I'll remove the interface to Boost.ConceptCheck or I can use any (alphanumeric) mane rather than requires (e.g., where).
However, I can use the requires clausule to do multiple things: 1. Check concepts defined using Boost.ConceptCheck (current, I'd leave it as is). 2. Check static_assert (under consideration, to be moved here from within pre/post/inv). 3. Check Boost.Generic-like concepts implemented using C++11 expression SFINAE (for future... this will be *a lot* of work...). I should be able to support of all those because I can distinguish 2 using the pp (starts with static_assert)
I will really prefer the static_assert goes outside requires, e.g. in a new *check* clause. This clause could also contain the ConceptCheck part. In this way it is clear that the requires part will disable the instantiation if not satisfied, and the check part will report a compile-time error if not satisfied.
and I can distinguish between 1 and 2 using the compiler for example using a (hidden) tagging base class to all concepts defined for 3.
I'm not sure this distinction is possible. For function templates, the requires part associated to ConceptCheck should be included in the function definition, while the one associated to enable_if/SFINAE c++ proposal concepts emulation should be part of the C++ declaration. For template classes, ConceptCheck goes to the members part, while Concepts goes to the template parameter part.
As you can see the semantics are different, so a specific keyword would help to identify the difference.
Can you provide an example of how all of this would ideally look like? You can also pick a "keyword" other than requires that makes sense to you and then indicate where to use requires and where to use the other keyword in the example. Maybe you start from the static_assert example I gave: template< typename To, typename From > requires // new concepts?? Convertible<From, To> // disable this declaration using SFINAE?? unless // static_assert and Boost.ConceptCheck?? static_assert(sizeof(To) >= sizeof(From), "destination too small"), // generate compiler-error?? boost::Copyable<From> // generate compiler-error?? To* memcopy ( To* to, From* from ) precondition { to; // pointer not null from; // pointer not null } { // ... } Or any other example will do but I want to fully understand what your idea is. Thanks :)
IMO, I'd stick with requires, leave 1 as is, maybe add 2 for now, and consider 3 for future.
* static assertions are removed from the pre/post conditions. They can be moved to a specific "static assertions" section at the same level than the requires clause. This section could also include the concept check included now in the requires clause.
OK (but I'd personally bundle all into requires).
* The library extends the EDSL to use directly C++11 features, in particular move semantics. Now that since the C++11 standard is released, more and more people are using C++11 specific features. I, in particular, will not use Contract if I can not make use of C++11 features provided by the compiler.
I'd prefer to add C++11 in future releases because the lib is usable as is for C++03 and adding the C++11 features will take time but it won't break the interface. Of course, I'll comply with whatever the final decision is.
* The contract broken handlers are noexcept, so that adding contracts don't change the original prototype.
They will be when C++11 support is added (again, I'd prefer later but I'm OK otherwise even if that will delay a possible release).
If you are allowed to release without C++11 support, it will be great if the documentation states clearly that the contract broken handlers can not throw. Otherwise, when moving to C++11, the C++03 usage will be broken. Even if you don't take care of C++11 features for the functions declaration, you could request that the contract broken handlers are noexcept using the Boost macro BOOST_NOEXCEPT, which is empty in C++03.
OK, makes sense. Thanks! --Lorenzo

2012/9/4 Lorenzo Caminiti <lorcaminiti@gmail.com>
Le 03/09/12 00:14, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 2:39 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Hi,
here is my short review.
My vote is YES subject to these condition.
Thanks a lot for the review.
* Removal of the Concepts part. The use of Boost.ConceptCheck to emulate C++ concepts proposal is in my opinion erroneous. Boost.Concept.Check is used to assert the actual parameter satisfy statically the concept conditions, while if I'm not wrong the C++ Concepts proposal use the requires clause to state the conditions of a possible instantiations. Using the same grammar with different semantics is confusing. In a last resort, if this feature is preserved, the requires keyword must be changed by another one.
If that were to be the final decision, I'll remove the interface to Boost.ConceptCheck or I can use any (alphanumeric) mane rather than requires (e.g., where).
However, I can use the requires clausule to do multiple things: 1. Check concepts defined using Boost.ConceptCheck (current, I'd leave it as is). 2. Check static_assert (under consideration, to be moved here from within pre/post/inv). 3. Check Boost.Generic-like concepts implemented using C++11 expression SFINAE (for future... this will be *a lot* of work...). I should be able to support of all those because I can distinguish 2 using the pp (starts with static_assert)
I will really prefer the static_assert goes outside requires, e.g. in a new *check* clause. This clause could also contain the ConceptCheck part. In this way it is clear that the requires part will disable the instantiation if not satisfied, and the check part will report a compile-time error if not satisfied.
and I can distinguish between 1 and 2 using the compiler for example using a (hidden) tagging base class to all concepts defined for 3.
I'm not sure this distinction is possible. For function templates, the requires part associated to ConceptCheck should be included in the function definition, while the one associated to enable_if/SFINAE c++ proposal concepts emulation should be part of the C++ declaration. For template classes, ConceptCheck goes to the members part, while Concepts goes to
On Sun, Sep 2, 2012 at 11:14 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote: the
template parameter part.
As you can see the semantics are different, so a specific keyword would help to identify the difference.
Can you provide an example of how all of this would ideally look like? You can also pick a "keyword" other than requires that makes sense to you and then indicate where to use requires and where to use the other keyword in the example. Maybe you start from the static_assert example I gave:
template< typename To, typename From > requires // new concepts?? Convertible<From, To> // disable this declaration using SFINAE?? unless // static_assert and Boost.ConceptCheck?? static_assert(sizeof(To) >= sizeof(From), "destination too small"), // generate compiler-error?? boost::Copyable<From> // generate compiler-error?? To* memcopy ( To* to, From* from ) precondition { to; // pointer not null from; // pointer not null } { // ... }
Or any other example will do but I want to fully understand what your idea is. Thanks :)
Oh, I did not realize that Boost.ConceptCheck does not use SFINAE-based techniques. In that case, given that you only check constraints and do not have SFINAE-based concepts, the ideal syntax (macro-free) would be something like: template< typename To, typename From > static_assert(sizeof(To) >= sizeof(From), "dest too small"), static assert(Copyable<From>, "2nd arg not copyable") To* memcopy ( To* to, From* from ) precondition { to != nullptr; from != nullptr; } { // ... } Although, it may not be achievable with current Boost.ConceptCheck because Copyable<From> is not a predicate; or is it? On the other hand, I am not sure how much value it adds over putting static asserts inside function body. In C++ in case of templates we are forced and used to provide definitions along declarations. Regards, &rzej

On Tue, Sep 4, 2012 at 1:03 AM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
2012/9/4 Lorenzo Caminiti <lorcaminiti@gmail.com>
Le 03/09/12 00:14, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 2:39 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Hi,
here is my short review.
My vote is YES subject to these condition.
Thanks a lot for the review.
* Removal of the Concepts part. The use of Boost.ConceptCheck to emulate C++ concepts proposal is in my opinion erroneous. Boost.Concept.Check is used to assert the actual parameter satisfy statically the concept conditions, while if I'm not wrong the C++ Concepts proposal use the requires clause to state the conditions of a possible instantiations. Using the same grammar with different semantics is confusing. In a last resort, if this feature is preserved, the requires keyword must be changed by another one.
If that were to be the final decision, I'll remove the interface to Boost.ConceptCheck or I can use any (alphanumeric) mane rather than requires (e.g., where).
However, I can use the requires clausule to do multiple things: 1. Check concepts defined using Boost.ConceptCheck (current, I'd leave it as is). 2. Check static_assert (under consideration, to be moved here from within pre/post/inv). 3. Check Boost.Generic-like concepts implemented using C++11 expression SFINAE (for future... this will be *a lot* of work...). I should be able to support of all those because I can distinguish 2 using the pp (starts with static_assert)
I will really prefer the static_assert goes outside requires, e.g. in a new *check* clause. This clause could also contain the ConceptCheck part. In this way it is clear that the requires part will disable the instantiation if not satisfied, and the check part will report a compile-time error if not satisfied.
and I can distinguish between 1 and 2 using the compiler for example using a (hidden) tagging base class to all concepts defined for 3.
I'm not sure this distinction is possible. For function templates, the requires part associated to ConceptCheck should be included in the function definition, while the one associated to enable_if/SFINAE c++ proposal concepts emulation should be part of the C++ declaration. For template classes, ConceptCheck goes to the members part, while Concepts goes to
On Sun, Sep 2, 2012 at 11:14 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote: the
template parameter part.
As you can see the semantics are different, so a specific keyword would help to identify the difference.
Can you provide an example of how all of this would ideally look like? You can also pick a "keyword" other than requires that makes sense to you and then indicate where to use requires and where to use the other keyword in the example. Maybe you start from the static_assert example I gave:
template< typename To, typename From > requires // new concepts?? Convertible<From, To> // disable this declaration using SFINAE?? unless // static_assert and Boost.ConceptCheck?? static_assert(sizeof(To) >= sizeof(From), "destination too small"), // generate compiler-error?? boost::Copyable<From> // generate compiler-error?? To* memcopy ( To* to, From* from ) precondition { to; // pointer not null from; // pointer not null } { // ... }
Or any other example will do but I want to fully understand what your idea is. Thanks :)
Oh, I did not realize that Boost.ConceptCheck does not use SFINAE-based techniques. In that case, given that you only check constraints and do not have SFINAE-based concepts, the ideal syntax (macro-free) would be something like:
template< typename To, typename From > static_assert(sizeof(To) >= sizeof(From), "dest too small"), static assert(Copyable<From>, "2nd arg not copyable") To* memcopy ( To* to, From* from ) precondition { to != nullptr; from != nullptr; } { // ... }
Although, it may not be achievable with current Boost.ConceptCheck because Copyable<From> is not a predicate; or is it?
No, it's not :( My understand is that the set of conditions for with you can program predicates is smaller than the one for which you can generate a compiler error in C++.
On the other hand, I am not sure how much value it adds over putting static asserts inside function body. In C++ in case of templates we are forced and used to provide definitions along declarations.
Thanks. --Lorenzo

Le 04/09/12 03:01, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 11:14 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 03/09/12 00:14, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 2:39 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Hi,
here is my short review.
My vote is YES subject to these condition. Thanks a lot for the review.
* Removal of the Concepts part. The use of Boost.ConceptCheck to emulate C++ concepts proposal is in my opinion erroneous. Boost.Concept.Check is used to assert the actual parameter satisfy statically the concept conditions, while if I'm not wrong the C++ Concepts proposal use the requires clause to state the conditions of a possible instantiations. Using the same grammar with different semantics is confusing. In a last resort, if this feature is preserved, the requires keyword must be changed by another one. If that were to be the final decision, I'll remove the interface to Boost.ConceptCheck or I can use any (alphanumeric) mane rather than requires (e.g., where).
However, I can use the requires clausule to do multiple things: 1. Check concepts defined using Boost.ConceptCheck (current, I'd leave it as is). 2. Check static_assert (under consideration, to be moved here from within pre/post/inv). 3. Check Boost.Generic-like concepts implemented using C++11 expression SFINAE (for future... this will be *a lot* of work...). I should be able to support of all those because I can distinguish 2 using the pp (starts with static_assert) I will really prefer the static_assert goes outside requires, e.g. in a new *check* clause. This clause could also contain the ConceptCheck part. In this way it is clear that the requires part will disable the instantiation if not satisfied, and the check part will report a compile-time error if not satisfied.
and I can distinguish between 1 and 2 using the compiler for example using a (hidden) tagging base class to all concepts defined for 3. I'm not sure this distinction is possible. For function templates, the requires part associated to ConceptCheck should be included in the function definition, while the one associated to enable_if/SFINAE c++ proposal concepts emulation should be part of the C++ declaration. For template classes, ConceptCheck goes to the members part, while Concepts goes to the template parameter part.
As you can see the semantics are different, so a specific keyword would help to identify the difference. Can you provide an example of how all of this would ideally look like? You can also pick a "keyword" other than requires that makes sense to you and then indicate where to use requires and where to use the other keyword in the example. Maybe you start from the static_assert example I gave:
template< typename To, typename From > requires // new concepts?? Convertible<From, To> // disable this declaration using SFINAE?? unless // static_assert and Boost.ConceptCheck?? static_assert(sizeof(To) >= sizeof(From), "destination too small"), // generate compiler-error?? boost::Copyable<From> // generate compiler-error?? To* memcopy ( To* to, From* from ) precondition { to; // pointer not null from; // pointer not null } { // ... }
I will use *check* as keyword for the static_assert and ConceptCheck part template< typename To, typename From > requires // used with enable_if in the declaration part is_convertible<From, To>::value check // included in the function body assert(sizeof(To) >= sizeof(From), "destination too small") && boost::Copyable<From> To* memcopy ( To* to, From* from ) precondition { to; // pointer not null from; // pointer not null } { // ... } You could also use the check sizeof(To) >= sizeof(From) in the requires part if you wanted to disable overload resolution when the condition fails as in template< typename To, typename From > requires // used with enable_if in the declaration part is_convertible<From, To>::value && sizeof(To) >= sizeof(From) check // included in the function body boost::Copyable<From> To* memcopy ( To* to, From* from ) // ... Note however that the Concept Copyable from ConceptCheck can not be used in the requires clause (I'm looking for), it is not a bool metafunction (or a trait). It just compile fail when the parameter doesn't models the concept. HTH, Vicente
Or any other example will do but I want to fully understand what your idea is. Thanks :)

On Tue, Sep 4, 2012 at 4:01 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 04/09/12 03:01, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 11:14 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 03/09/12 00:14, Lorenzo Caminiti a écrit :
On Sun, Sep 2, 2012 at 2:39 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Hi,
here is my short review.
My vote is YES subject to these condition.
Thanks a lot for the review.
* Removal of the Concepts part. The use of Boost.ConceptCheck to emulate C++ concepts proposal is in my opinion erroneous. Boost.Concept.Check is used to assert the actual parameter satisfy statically the concept conditions, while if I'm not wrong the C++ Concepts proposal use the requires clause to state the conditions of a possible instantiations. Using the same grammar with different semantics is confusing. In a last resort, if this feature is preserved, the requires keyword must be changed by another one.
If that were to be the final decision, I'll remove the interface to Boost.ConceptCheck or I can use any (alphanumeric) mane rather than requires (e.g., where).
However, I can use the requires clausule to do multiple things: 1. Check concepts defined using Boost.ConceptCheck (current, I'd leave it as is). 2. Check static_assert (under consideration, to be moved here from within pre/post/inv). 3. Check Boost.Generic-like concepts implemented using C++11 expression SFINAE (for future... this will be *a lot* of work...). I should be able to support of all those because I can distinguish 2 using the pp (starts with static_assert)
I will really prefer the static_assert goes outside requires, e.g. in a new *check* clause. This clause could also contain the ConceptCheck part. In this way it is clear that the requires part will disable the instantiation if not satisfied, and the check part will report a compile-time error if not satisfied.
and I can distinguish between 1 and 2 using the compiler for example using a (hidden) tagging base class to all concepts defined for 3.
I'm not sure this distinction is possible. For function templates, the requires part associated to ConceptCheck should be included in the function definition, while the one associated to enable_if/SFINAE c++ proposal concepts emulation should be part of the C++ declaration. For template classes, ConceptCheck goes to the members part, while Concepts goes to the template parameter part.
As you can see the semantics are different, so a specific keyword would help to identify the difference.
Can you provide an example of how all of this would ideally look like? You can also pick a "keyword" other than requires that makes sense to you and then indicate where to use requires and where to use the other keyword in the example. Maybe you start from the static_assert example I gave:
template< typename To, typename From > requires // new concepts?? Convertible<From, To> // disable this declaration using SFINAE?? unless // static_assert and Boost.ConceptCheck?? static_assert(sizeof(To) >= sizeof(From), "destination too small"), // generate compiler-error?? boost::Copyable<From> // generate compiler-error?? To* memcopy ( To* to, From* from ) precondition { to; // pointer not null from; // pointer not null } { // ... }
I will use *check* as keyword for the static_assert and ConceptCheck part
template< typename To, typename From > requires // used with enable_if in the declaration part is_convertible<From, To>::value check // included in the function body
assert(sizeof(To) >= sizeof(From), "destination too small") && boost::Copyable<From>
To* memcopy ( To* to, From* from ) precondition { to; // pointer not null from; // pointer not null } { // ... }
You could also use the check
sizeof(To) >= sizeof(From)
in the requires part if you wanted to disable overload resolution when the condition fails as in
template< typename To, typename From > requires // used with enable_if in the declaration part is_convertible<From, To>::value && sizeof(To) >= sizeof(From) check // included in the function body boost::Copyable<From>
To* memcopy ( To* to, From* from ) // ...
Note however that the Concept Copyable from ConceptCheck can not be used in the requires clause (I'm looking for), it is not a bool metafunction (or a trait). It just compile fail when the parameter doesn't models the concept.
This makes sense to me and, as far as I can tell, it is also in line with Andrzej suggestion. I'm happy to implement it this way. CONTRACT_FUNCTION( template( typename To, typename From ) requires( // used with enable_if in the declaration part is_convertible<From, To>::value, is_convertible<To, From>::value ) check( // included in the function body static_assert(sizeof(To) >= sizeof(From), "destination too small"), boost::Copyable<From> ) (To*) memcopy ( (To*) to, (From*) from ) precondition( to; // pointer not null from; // pointer not null ) ) { // ... } I will implement the check clausule now and the require one later and only if I'm able to extend the lib to declare and check Boost.Generic-like concepts. Just to consider all alternatives, we could also do this: CONTRACT_FUNCTION( template( typename To, typename From ) if( // used with enable_if in the declaration part is_convertible<From, To>::value, is_convertible<To, From>::value ) requires( // included in the function body static_assert(sizeof(To) >= sizeof(From), "destination too small"), boost::Copyable<From> ) (To*) memcopy ( (To*) to, (From*) from ) precondition( to; // pointer not null from; // pointer not null ) ) { // ... } Given that the 1st clausule is more like enable-if and the 2nd clausule states "hard" requirements (in that you get a "hard" compiler errors when the requirements are not met). But I'm happy with requires/check and if/requires the same way (and I still haven't read N3331 which might suggest a syntax vs another...). Thanks, --Lorenzo

Just to consider all alternatives, we could also do this:
CONTRACT_FUNCTION( template( typename To, typename From ) if( // used with enable_if in the declaration part is_convertible<From, To>::value, is_convertible<To, From>::value ) requires( // included in the function body static_assert(sizeof(To) >= sizeof(From), "destination too small"), boost::Copyable<From> ) (To*) memcopy ( (To*) to, (From*) from ) precondition( to; // pointer not null from; // pointer not null ) ) { // ... }
We (or I) are too much used to "requires" implying concepts, implying enable-if behavior. So I would find this one confusing. Although the "if" makes sense. One other alternative would be: keyword "enable_if" -- for soft conditions keyword "expect" or "check" -- for hard conditions But your first suggestion is satisfactory. Regards, &rzej

on Tue Sep 04 2012, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
Just to consider all alternatives, we could also do this:
CONTRACT_FUNCTION( template( typename To, typename From ) if( // used with enable_if in the declaration part is_convertible<From, To>::value, is_convertible<To, From>::value )
+1 for "if." Andrzej's "enable_if" suggestion is nice and more explicit too, but there's no syntax highlighting bonus. I'm torn.
requires( // included in the function body
The fact that this is "included in the function body" is irrelevant I think. I guess the real point you're trying to make is that it generates hard errors at acompile time when violated. That suggests something like "asserts" instead of "requires."
static_assert(sizeof(To) >= sizeof(From), "destination too small"), boost::Copyable<From> ) (To*) memcopy ( (To*) to, (From*) from ) precondition( to; // pointer not null from; // pointer not null ) ) { // ... }
-- Dave Abrahams BoostPro Computing Software Development Training http://www.boostpro.com Clang/LLVM/EDG Compilers C++ Boost

On Sun, Sep 16, 2012 at 6:27 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Tue Sep 04 2012, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
Just to consider all alternatives, we could also do this:
CONTRACT_FUNCTION( template( typename To, typename From ) if( // used with enable_if in the declaration part is_convertible<From, To>::value, is_convertible<To, From>::value )
+1 for "if." Andrzej's "enable_if" suggestion is nice and more explicit too, but there's no syntax highlighting bonus. I'm torn.
requires( // included in the function body
The fact that this is "included in the function body" is irrelevant I think. I guess the real point you're trying to make is that it generates hard errors at acompile time when violated. That suggests something like "asserts" instead of "requires."
Then I think "check" for hard errors and "requires" for SFINAE is a good choice (requires better than if or enable_if for SFINAE I think...). I will read N3351 and check again with this ML before making a final decision: http://sourceforge.net/apps/trac/contractpp/ticket/96
static_assert(sizeof(To) >= sizeof(From), "destination too small"), boost::Copyable<From> ) (To*) memcopy ( (To*) to, (From*) from ) precondition( to; // pointer not null from; // pointer not null ) ) { // ... }
Thanks, --Lorenzo

on Sun Sep 16 2012, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
On Sun, Sep 16, 2012 at 6:27 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Tue Sep 04 2012, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
Just to consider all alternatives, we could also do this:
CONTRACT_FUNCTION( template( typename To, typename From ) if( // used with enable_if in the declaration part is_convertible<From, To>::value, is_convertible<To, From>::value )
+1 for "if." Andrzej's "enable_if" suggestion is nice and more explicit too, but there's no syntax highlighting bonus. I'm torn.
requires( // included in the function body
The fact that this is "included in the function body" is irrelevant I think. I guess the real point you're trying to make is that it generates hard errors at acompile time when violated. That suggests something like "asserts" instead of "requires."
Then I think "check" for hard errors and "requires" for SFINAE is a good choice (requires better than if or enable_if for SFINAE I think...).
I don't see what justifies any of those conclusions. Neither "check" nor "requires" particularly implies hard errors or SFINAE. enable_if does, even if you don't know what SFINAE is. -- Dave Abrahams BoostPro Computing Software Development Training http://www.boostpro.com Clang/LLVM/EDG Compilers C++ Boost

On Mon, Sep 17, 2012 at 10:06 AM, Dave Abrahams <dave@boostpro.com> wrote:
on Sun Sep 16 2012, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
On Sun, Sep 16, 2012 at 6:27 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Tue Sep 04 2012, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
Just to consider all alternatives, we could also do this:
CONTRACT_FUNCTION( template( typename To, typename From ) if( // used with enable_if in the declaration part is_convertible<From, To>::value, is_convertible<To, From>::value )
+1 for "if." Andrzej's "enable_if" suggestion is nice and more explicit too, but there's no syntax highlighting bonus. I'm torn.
requires( // included in the function body
The fact that this is "included in the function body" is irrelevant I think. I guess the real point you're trying to make is that it generates hard errors at acompile time when violated. That suggests something like "asserts" instead of "requires."
Then I think "check" for hard errors and "requires" for SFINAE is a good choice (requires better than if or enable_if for SFINAE I think...).
I don't see what justifies any of those conclusions. Neither "check" nor "requires" particularly implies hard errors or SFINAE. enable_if does, even if you don't know what SFINAE is.
I'll keep all the options open but I want to read N3351 before making an actual proposal. I will check with this ML before making a final decision so we can all agree on the names to use (of course any name requires, check, if, enable_if, etc is fine from an implementation prospective). BTW, I'm using requires also to express: 1. Assertion requirements. Those disable assertion compilation and checking when they are not met--no hard error. 2. Boost.Parameter predicate type requirements. (As you know well) those latter ones are unary boolean meta-functions that disable the function declaration in case they are not met--no hard error. I will also consider consistency with these other usages of requires in proposing the name. Thanks. --Lorenzo
participants (4)
-
Andrzej Krzemienski
-
Dave Abrahams
-
Lorenzo Caminiti
-
Vicente J. Botet Escriba