[contract] syntax redesign

Hello all, After a long time of inactivity for Boost.Contract, I am considering how to re-design its macro syntax to make it simpler. I can eliminate a large number of extra parenthesis based on a few pp tricks I've learned in processing Boost.Local's `const bind(type)& var`. Plus, I can provide (optional) support for variadics macros so to use comma-separated pp tuplets instead of parenthesized pp sequences on preprocessors with variadics. For example, I _think_ (but I've not implemented this yet) that I can simplify the syntax like this: #include <contract.hpp> #include <vector> #include "myvector/pushable.hpp" // Wrapper class that adds contracts to std::vector. CONTRACT_CLASS( template( typename T ) class (myvector) extends( public pushable<T> ) // Subcontracting. ) { CONTRACT_CLASS_INVARIANT( empty() == (size() == 0) // More invariants here (comma separated)... ) CONTRACT_FUNCTION( public void (push_back)( (const T&) element ) precondition( size() < max_size() // More preconditions here (comma separated)... ) postcondition( auto old_size = CONTRACT_OLDOF(size()), // Old value. size() == old_size + 1 // More postconditions here (comma separated)... ) ) { vector_.push_back(element); // Implementation. } // Rest of the class here (with more contracts if needed)... public: typedef typename std::vector<T>::size_type size_type; size_type size(void) const { return vector_.size(); } size_type max_size(void) const { return vector_.max_size(); } bool empty(void) const { return vector_.empty(); } const T& back(void) const { return vector_.back(); } private: std::vector<T> vector_; }; For a side-by-side comparison with N1962 syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/index... For a comparison of the entire std::vector (plus Boost.ConceptCheck concepts): http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contr... For a comparison for all Boost.Contract features (plus Boost.ConceptCheck concepts and Boost.Parameter named parameters): http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contr... (Don't pay attention to the rest of the docs that are way out of date.) A few notes: * Extra parenthesis are still needed around class and function names. * Extra parenthesis are still needed around types (like for the parameter `(T) element`) but only if the type is not a C++ keyword (no parenthesis needed aournd int, double, void, etc) or it contains a symbol (parenthesis needed if & or * are used `(int&) x`, etc). * In postconditions, the `auto old_size = CONTRACT_OLDOF(size())` only copies the vector size (and not the entire vector :)) ). Similarly, `auto result = return` can be used to access the return value for non-void functions. (The `auto ...` is parsed by the pp and it's implemented using Boost.Typeof so no C++0x is required.) * Template declaration (but not instantiation) angular parenthesis <> are replaced by round parenthesis (). All of this _should_ be implementable in pure ISO C++. What do you think? Based on the discontent that the previous "parenthesized" syntax generated among Boosters, the key question is: Would you consider this new syntax usable?? Thanks, --Lorenzo

On Tue, May 31, 2011 at 2:49 PM, Lorenzo Caminiti <lorcaminiti@gmail.com>wrote:
For example, I _think_ (but I've not implemented this yet) that I can simplify the syntax like this:
Looks good, I use pretty much exactly the same syntax in my library concerning parameter lists and templates ( https://github.com/boostcon/2011_presentations/raw/master/thu/Boost.Generic.... slides 79 and 96 are okay examples). The only thing I'm confused about is how you specify the return type of your CONTRACT_FUNCTION -- in particular, you did not wrap it in parentheses. Are you really able to do that, or is that a mistake? If that syntax is indeed possible, then I'd like to see the implementation because I too would love to be able to rid myself of some parentheses. -- -Matt Calabrese

Matt Calabrese wrote:
On Tue, May 31, 2011 at 2:49 PM, Lorenzo Caminiti <lorcaminiti@gmail.com>wrote:
For example, I _think_ (but I've not implemented this yet) that I can simplify the syntax like this:
Looks good, I use pretty much exactly the same syntax in my library concerning parameter lists and templates ( https://github.com/boostcon/2011_presentations/raw/master/thu/Boost.Generic.... slides 79 and 96 are okay examples). The only thing I'm confused about is how you
Thanks, I'll take a look.
specify the return type of your CONTRACT_FUNCTION -- in particular, you did not wrap it in parentheses. Are you really able to do that, or is that a
If the return type is a "keyword" known a priori like void then no parenthesis should be needed. I'd parse it using the pp PP_IS_UNARY to first check if there are parenthesis. If there are no parenthesis then I'd check if the token is a known "keyword" type `void`, `int`, `double`, etc using macros like BOOST_DETAIL_PP_KEYWORD_IS_VOID_FRONT and strip it aways from the front using macros like BOOST_DETAIL_PP_KEYWORD_VOID_REMOVE_FRONT (see http://svn.boost.org/svn/boost/sandbox/local/boost/detail/preprocessor/keywo...). So, this does not need the parenthesis because int is a "keyword" known a priory (void return type also belongs to this category): CONTRACT_FUNCTION( public int (size)() ... ) This instead needs the parenthesis because my_own_size_type is a user-defined type and it's not known a priory: CONTRACT_FUNCTION( public (my_own_size_type) (size)() ... ) Also this needs the parenthesis because int* contains a non-alphanumeric symbol * that cannot be handled by the BOOST_DETAIL_PP_KEYWORD_XXX macros (because they use pp concatenation): CONTRACT_FUNCTION( public (int*) (size)() ... ) The same applies to all specified types including function parameter types `void (f)( int x, int y )` vs. `void (f)( (int*) x, int y )`.
mistake? If that syntax is indeed possible, then I'd like to see the implementation because I too would love to be able to rid myself of some parentheses.
I have done some experimentation that indicates this syntax _should_ be possible but it's not actually implemented yet so... we'll see :) --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p356438... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Tue, May 31, 2011 at 5:21 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
If the return type is a "keyword" known a priori like void then no parenthesis should be needed.
Oh, so you just special-cased some keywords and the rest require parentheses? That's good. The only criticism I have of that is that it's inconsistent. I had some special-casing to eliminate parentheses, similar to what you are doing, but I ultimately sided on being consistent over everything else. That's obviously just my opinion, so I'm not saying you should definitely change it, it's just something to consider. Also, given your description (using IS_UNARY), it sounds as though your current implementation cannot handle return types that have top-level commas. For instance, you can't return a boost::array< int, 2 > directly without using a typedef (and if that return type is dependent on the function's template parameters then you could potentially be stuck). I highly recommend that you use variadic macros here to directly check if it's anything parenthesized other than empty. It looks like you're already relying on variadic macros for your parameter lists, so you wouldn't be introducing further compiler requirements.
I have done some experimentation that indicates this syntax _should_ be possible but it's not actually implemented yet so... we'll see :)
It's definitely possible, yes. -- -Matt Calabrese

Matt Calabrese wrote:
On Tue, May 31, 2011 at 5:21 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
If the return type is a "keyword" known a priori like void then no parenthesis should be needed.
Oh, so you just special-cased some keywords and the rest require parentheses? That's good. The only criticism I have of that is that it's inconsistent. I had some special-casing to eliminate parentheses, similar to what you are doing, but I ultimately sided on being consistent over everything else. That's obviously just my opinion, so I'm not saying you should definitely change it, it's just something to consider.
Yes, I was also concerned about inconsistency so I decided that the syntax will always accept parenthesized types. You can (but don't have to) omit the parenthesis for a known "keyword". This way users can choose as they wish. In other words, the following will both be accepted by the same macros: CONTRACT_FUNCTION( (void) (f)() ) // (1) CONTRACT_FUNCTION( void (f)() ) // (2) If you are worry about consistency, you use (1). If you are worried abut extra parenthesis, you use (2).
Also, given your description (using IS_UNARY), it sounds as though your current implementation cannot handle return types that have top-level commas. For instance, you can't return a boost::array< int, 2 > directly without using a typedef (and if that return type is dependent on the function's template parameters then you could potentially be stuck). I highly recommend that you use variadic macros here to directly check if it's anything parenthesized other than empty. It looks like you're already
Boost.Local's BOOST_IDENTITY_TYPE can be used to handle un-parenthesized commas within macro parameters (see http://svn.boost.org/svn/boost/sandbox/local/boost/utility/identity.hpp).
relying on variadic macros for your parameter lists, so you wouldn't be introducing further compiler requirements.
Similarly to Boost.Local, the syntax will require parenthesis on preprocessors without variadics: CONTRACT_FUNCTION( void (f)( (int x) (int y) ) ... ) // no variadics must use this With variadics, you can still use the above or alternatively the same macros will accept commas: CONTRACT_FUNCTION( void (f)( int x, int y ) ... ) // variadics can (but don't have to) use this
I have done some experimentation that indicates this syntax _should_ be possible but it's not actually implemented yet so... we'll see :)
It's definitely possible, yes.
--Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p356446... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Tue, May 31, 2011 at 5:59 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
Boost.Local's BOOST_IDENTITY_TYPE can be used to handle un-parenthesized commas within macro parameters (see http://svn.boost.org/svn/boost/sandbox/local/boost/utility/identity.hpp).
Ah, so for a user to specify a return type of array< int, 2 >, they'd do: (BOOST_IDENTITY_TYPE((array<int,2>)))(function_name)(params) cv-qualifiers? That's great. You seem to be putting a lot of effort into supporting compilers both with and without variadics. The only problem I can think of is that the IDENTITY_TYPE kind of trick doesn't work for function parameters where the template argument is to be automatically deduced. For that case, I think variadics are unfortunately necessary. -- -Matt Calabrese

Matt Calabrese wrote:
On Tue, May 31, 2011 at 5:59 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
Boost.Local's BOOST_IDENTITY_TYPE can be used to handle un-parenthesized commas within macro parameters (see http://svn.boost.org/svn/boost/sandbox/local/boost/utility/identity.hpp).
Ah, so for a user to specify a return type of array< int, 2 >, they'd do:
(BOOST_IDENTITY_TYPE((array<int,2>)))(function_name)(params) cv-qualifiers?
Yes, including trailing cv-qualifiers, throw(...), etc and for my lib including precondition(...), postcondition(...).
That's great. You seem to be putting a lot of effort into supporting compilers both with and without variadics.
Yes, I'd prefer the lib to be ISO C++ compliant.
The only problem I can think of is that the IDENTITY_TYPE kind of trick doesn't work for function parameters where the template argument is to be automatically deduced.
For example? (Just so I understand this case correctly.) Thanks, --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p356454... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Tue, May 31, 2011 at 6:35 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
For example? (Just so I understand this case correctly.)
////////// CONTRACT_FUNCTION( public template( class T, class Alloc ) void (push_back)( (BOOST_IDENTITY_TYPE((std::vector< T, Alloc >&))) vector_, (const T&) element ) { vector_.push_back(element); } ////////// In the above case, since the first parameter type actually ends up being the result of a metafunction invocation, you can't simply call the function by doing this_.push_back( an_instance_of_std_vector, 4 ). T and Alloc can no longer be deduced. -- -Matt Calabrese

Matt Calabrese wrote:
On Tue, May 31, 2011 at 6:35 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
For example? (Just so I understand this case correctly.)
////////// CONTRACT_FUNCTION( public template( class T, class Alloc ) void (push_back)( (BOOST_IDENTITY_TYPE((std::vector< T, Alloc >&))) vector_, (const T&) element ) { vector_.push_back(element); } //////////
In the above case, since the first parameter type actually ends up being the result of a metafunction invocation, you can't simply call the function by doing this_.push_back( an_instance_of_std_vector, 4 ). T and Alloc can no longer be deduced.
Yes, I see: #include <boost/type_traits.hpp> #include <memory> #include <vector> #include <iostream> #define IDENTITY_TYPE(paren_type) \ boost::function_traits< void paren_type >::arg1_type template< typename T, class Alloc > void push_back( // comma in type is now wrapped in parenthesis (ok for macros) typename IDENTITY_TYPE((std::vector< T, Alloc >&)) vector, const T& element ) { vector.push_back(element); } int main() { std::vector<int> v; // push_back(v, -1); // Error: Can't deduce vector type via IDENTITY_TYPE. push_back< int, std::allocator<int> >(v, -1); // OK but no type deduction :(( std::cout << v[0] << std::endl; return 0; } Questions: 1) How bad is this? I am afraid that giving up this kind of automatic type deduction makes generic programming less convenient... am I right? ( I'm not a generic programmer ;) ) 2) Does anyone know of a better way to handle commas within macro parameter types but without using variadics? Note: Because of this I will try to provide a different implementation of IDENTITY_TYPE when variadics are supported (however, to properly handle the types with commas I think that not just IDENTITY_TYPE but also the CONTRACT macros need to modified to be aware that the type if a pp tuple). The same applies to Boost.Local macros. Thanks a lot! --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p356591... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Wed, Jun 1, 2011 at 10:01 AM, lcaminiti <lorcaminiti@gmail.com> wrote:
Questions: 1) How bad is this? I am afraid that giving up this kind of automatic type deduction makes generic programming less convenient... am I right? ( I'm not a generic programmer ;) )
Yes, it just makes things less convenient and that's pretty much all. It's really not that bad since it's not an incredibly common case. Just make the macro remove the parentheses when variadic macros are present.
2) Does anyone know of a better way to handle commas within macro parameter types but without using variadics?
The function parameter trick is pretty much the best (only?) way to handle that kind of problem, at least that I'm aware of, since there's not really anything you can do entirely during preprocessing without variadic macros. Anyway, many or most compilers support them now (they've been standard C for over a decade now) and, as I'm sure you know, variadic macros are in the C++0x FDIS, so they will be standard in C++ very soon. If I could recommend one thing, focus primarily on variadic macros and treat the non-variadic case as a workaround, if you maintain such support at all. Don't go overboard trying to account for users who don't have access to compilers that can deal with variadic macros unless someone is explicitly requesting support. The number of such users likely isn't very high at all and it will only be getting smaller. Working with variadics simplifies things greatly both for users and for yourself as an implementor. Anyway, good luck. Your interface looks awesome. -- -Matt Calabrese

Matt Calabrese wrote:
On Tue, May 31, 2011 at 2:49 PM, Lorenzo Caminiti <lorcaminiti@gmail.com>wrote:
For example, I _think_ (but I've not implemented this yet) that I can simplify the syntax like this:
Looks good, I use pretty much exactly the same syntax in my library concerning parameter lists and templates ( https://github.com/boostcon/2011_presentations/raw/master/thu/Boost.Generic.... slides 79 and 96 are okay examples). The only thing I'm confused about is how you
Hey Matt, I am still looking over your slides so sorry in advance if the following suggestions don't make sense... Is it possible remove some of the extra parenthesis from your examples on page 79 and 96 as I suggest below? If not, why? // Legend: // * Parenthesis `(token)` (no spaces around single token) are to wrap a single // token within extra parenthesis. // * Parenthesis `( token1 [, token2, ...] )` (spaces around token list) are to // specify a list of tokens. // Page 79 // // N2914 syntax: concept Iterator<typename X> : Semiregular<X> { MoveConstructible reference = typename X::reference; MoveConstructible postincrement_result; requires HasDereference<postincrement_result>; reference operator*(X&); reference operator*(X&&); X& operator++(X&); postincrement_result operator++(X&, int); } // Boost.Generic syntax: BOOST_GENERIC_CONCEPT ( (Iterator)( (typename) X ), ( public Semiregular<X> ) , ( (MoveConstructible) reference, typename X::reference ) , ( (MoveConstructible) postincrement_result ) , ( requires HasDereference<postincrement_result> ) , ( (reference)(operator dereference)( (X&) ) ) , ( (reference)(operator dereference)( (X&&) ) ) , ( (X&)(operator preincrement)( (X&) ) ) , ( (postincrement_result)(operator postincrement)( (X&), (int) ) ) ) // Is the following syntax possible? BOOST_GENERIC( // Use leading `concept` "keyword" to determine macro functionality. // `typename` doesn't need extra parenthesis. // `extends` is not necessary but I find it more readable. concept (Iterator)( typename X ) extends( public Semiregular<X> ) // Extra parenthesis after comma `, ( ... )` are not necessary. // BOOST_GENERIC_ASSIGN just expand to `,` but I find it more readable. , (MoveConstructible) reference BOOST_GENERIC_ASSIGN typename x::reference , (MoveConstructible) postincrement_result , requires HasDereference<postincrement_result> // `operator(symbol, name)` allow user to name the operators (name is any // arbitrary alphanumeric token) so no predefined operator name to learn. // Types `X&`, `X&&`, `int`, etc do not need extra parenthesis. , (reference) operator(*, deref)( X& ) , (reference) operator(*, deref)( X&& ) , (X&) operator(++, preinc)( X& ) , (postincrement_result) operator(++, postinc)( X&, int ) ) // Page 96 // // N2914 syntax: template<ObjectType T> concept_map RandomAccessIterator<T*> { typedef T value_type; typedef ptrdiff_t difference_type; typedef T& reference; typedef T* pointer; } // Boost.Generic syntax: BOOST_GENERIC_CONCEPT_MAP ( ( template ( (class) T ) ), (RandomAccessIterator)(T*) , ( typedef T value_type ) , ( typedef ptrdiff_t difference_type ) , ( typedef T& reference ) , ( typedef T* pointer ) ) // Is the following syntax possible? BOOST_GENERIC( // Use `concept_map` "keyword" to determine macro functionality. // Do you need ObjectType? Is was missing from above syntax... template( (ObjectType) T ) concept_map (RandomAccessIterator)( T* ) , typedef T value_type , typedef ptrdiff_t difference_type , typedef T& reference , typedef T* pointer ) --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p356834... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Thu, Jun 2, 2011 at 9:28 AM, lcaminiti <lorcaminiti@gmail.com> wrote:
Hey Matt, I am still looking over your slides so sorry in advance if the following suggestions don't make sense...
First, thank you so much for taking the time to do this. I don't think anyone other than myself has really picked apart the latest syntax and tried to improve it.
Is it possible remove some of the extra parenthesis from your examples on page 79 and 96 as I suggest below? If not, why? ... // Is the following syntax possible? BOOST_GENERIC( // Use leading `concept` "keyword" to determine macro functionality.
I considered this during implementation, and same with "auto" concepts, but decided against it for a few reasons. For one, it complicates the implementation for, imo, little or no gain, and it can impact compile-time, which is something that I consider a problem with the library at this point in time.
// `typename` doesn't need extra parenthesis.
It does if I want to be consistent with all parameter kinds, but I could special-case typename and class if I disallow fully qualified names as you currently do. Right now I support typename/class, value parameters, and soon varidiac parameters which will work via the syntax ( (ParameterKindHere,,,) SomeNameHere ). I'll give some thought to special-casing, but for now, it's more consistent for users and easier to preprocess if I don't do that, and fully qualified names are handled without problem. The more I look at your library though and the more you mention it, the more I question my choice, so it is possible I'll start special-casing things as you are doing, but I have a lot on my plate before I devote time to changing features that already work. // `extends` is not necessary but I find it more readable.
This was just because I wanted to use a keyword that an IDE would highlight. In the predecessor to this library I was using words that weren't keywords and Dave Abrahams suggested that I switch over to keywords, with a rationale that I ultimately agreed with (easy to remember, it's not highlighted if you make a typo). Extends is not and likely will not be a keyword in C++. Also, with concepts, there's no such thing as "private" or "protected" refinement -- the public there acts as "extends" acts in your example in that it's only used to signify that what follows is a list of less refined concepts. If I change it, the public part would just be replaced rather than both words being there, but I'd probably use "refines" instead of extends since that's the proper term in Generic Programming, though that too is not a keyword.
// BOOST_GENERIC_ASSIGN just expand to `,` but I find it more readable.
I'm not a big fan of that. I use , because it's short and simple, though I have considered (,) to make it jump out as being different and unambiguous. If you can provide a good rationale for BOOST_GENERIC_ASSIGN over those options, I'm open to it, but at this point I favor simplicitly over a big macro name (and my gut is that most users will too).
, (MoveConstructible) reference BOOST_GENERIC_ASSIGN typename
The encapsulating set of parentheses around each individual parameter are for important reasons. For one, your current example is actually ambiguous. ////////// (MoveConstructible) reference, typename something_here ////////// could either be a contrained typename requirement with a default, or it could be a constrained typename without a default followed by an unconstrained typename. The encapsulating parentheses is imo the simplest solution for users to remember and for implementation, although if I use something like (,) or BOOST_GENERIC_ASSIGN for default assignment I could disambiguate this particular issue that way. However, another issue is that the default may, itself, have commas in it. Without the encapsulating parentheses, I can't know if the next comma in a default is a parameter separator or a part of the default (for instance, a default of boost::array< int, 2 >). If I special-case it so that you have the option of wrapping the default in parentheses if it has commas, then it's ambiguous with the situation where there is no default and where the next parameter to the concept macro starts with parentheses, etc. I could keep trying to special-case further, or I could just make a single, consistent rule that's easy to remember as I've done. IMO, this option is simpler for both myself and users and also aids in keeping compile-times down. Also, since I am consistent with wrapping each parameter with parentheses, it is much easier for me to give descriptive error reporting if the user screws something up that I can catch at preprocessing time. For instance, if a user is creating a many-line concept, such as an allocator-like concept, and he makes a typo somewhere in the middle, I want to be able to give the best error possible, including a parameter number, that particular parameter text in full, and even be able to continue parsing the remaining parameters to the concept, catching other potential errors during preprocessing. If each parameter is wrapped in parentheses, it is much easier to do this -- any noticeable error that occurs in the middle of a given parameter, even if it involves something tricky like commas, does not affect the parsing of further parameters, and I'm able to output the full parameter text of the parameter with the error in a static assert without accidentally cutting off part of what the user thought was a single parameter but ends up not being the case because of a misplaced comma. Finally, the concept macro, as I'm sure you can imagine, is fairly nasty underneath the hood. One nice thing about the implementation, however, is that I handle most of the top-level implementation via a simple preprocessor for-each operation over all of the parameters after the name and refinements. Having the parameters consistently separated is what makes this directly possible without any difficulty -- since the parameters are just individual macro arguments, I use a construct that invokes a macro for each parameter. It doesn't require any complicated logic to figure out where individual parameters are separated, is very efficient, and it keeps the loop logic separate from the parsing of individual parameters.
// `operator(symbol, name)` allow user to name the operators
I can't use a symbol, and a user-provided name is unfortunately meaningless both to me and the user here. Associated operator requirements of concepts check if the operator is callable with respect to the pseudo-signature. The reason I use a fixed name is because, internally, I have to generate metafunctions during preprocessing that check to see if the operation is callable for the given parameter types, and what is generated can vary depending on which operator is used. In order to do this, I have to know, entirely during preprocessing, exactly which operator is specified. You can't do this if the user provides the symbol representation of the operator, and an arbitrary, user-specified name wouldn't help. The names I use come from N2914 standard concept names, so there is also some consistency here.
// Types `X&`, `X&&`, `int`, etc do not need extra parenthesis.
I could special case int and other built-ins, but I don't see how it would be possible to special case X, or X&, etc. The "X" is a user-defined concept parameter for that specific macro invocation, not a universal identifier that I'm using.
BOOST_GENERIC( // Use `concept_map` "keyword" to determine macro functionality.
Yes, I can do that, but again, it makes preprocessing more complicated, affects compile-time, and is one more place for a user to make a mistake that I would want to explicitly look for if I were to give an easy-to-read error message. Overall, I don't think I'm gaining enough, if anything, by pushing more stuff into the macro itself. In an ideal world, I agree, that looks cool, but I just don't think it's practical. Simply calling the macro BOOST_GENERIC_CONCEPT_MAP gives me all of the information that I need without additional preprocessing.
// Do you need ObjectType? Is was missing from above syntax...
Sorry, that's covered in the talk itself and is not directly in the slides (the video is not online yet, but I'll link it whenever whoever is doing post uploads it) -- I can't handle concept-constrained concept maps just yet and if it's not clear, ObjectType is a concept as opposed to a type. That's why the example is not exactly the same between the two. In the end, if you are curious, the syntax will be ////////// template( ((ObjectType)) T ) // or if I disallow fully-qualified names template( (concept ObjectType) T ) ////////// , typedef T value_type
, typedef ptrdiff_t difference_type , typedef T& reference , typedef T* pointer
No, that's not really possible in practice. The problem is that the typedefs themselves may contain commas in them and what comes after the comma could potentially be something not parenthesized that is not valid to concatenate with at preprocessing time. I.E. a bool argument with a !, etc. Trying to handle this syntax and do special casing would be complicated and incomplete. Worse, when someone does something that looks as though it should be valid but really is not, solely for preprocessor reasons that I can't explicitly check for such as the one mentioned above, they would get a strange preprocessor concatenation error that would likely be completely meaningless to them. I try hard to make it so that the user should not be seeing errors like that, and without them having to remember what may seem like arbitrary rules that only make sense if you have written something along the lines of this library or your library, or Boost.Parameter, etc. which most programmers have not. Even then, the issues are extremely subtle. Again, thanks for all of this feedback. I've been wanting another head to kind of tear things apart. If anything, I think I may go ahead and special-case parameters like void, class, typename, etc. though that won't be for a while. Not using a comma as a replacement for = when specifying defaults may happen too. All of the other special-casing and attempted removal of parentheses I'll have to give further thought to, but I think the current design has the least subtle gotchas. -- -Matt Calabrese

On Thu, Jun 2, 2011 at 1:56 PM, Matt Calabrese <rivorus@gmail.com> wrote:
Not using a comma as a replacement for = when specifying defaults may happen too.
Actually, I just realized that (,) is not even an option, so there goes that. Unless you can come up with something other than , that BOOST_GENERIC_ASSIGN would expand out to, I think I'm going to stick with comma. Maybe two commas :/ -- -Matt Calabrese

On Thu, Jun 2, 2011 at 1:56 PM, Matt Calabrese <rivorus@gmail.com> wrote:
On Thu, Jun 2, 2011 at 9:28 AM, lcaminiti <lorcaminiti@gmail.com> wrote:
Hey Matt, I am still looking over your slides so sorry in advance if the following suggestions don't make sense...
First, thank you so much for taking the time to do this. I don't think anyone other than myself has really picked apart the latest syntax and tried to improve it.
:)
Is it possible remove some of the extra parenthesis from your examples on page 79 and 96 as I suggest below? If not, why? ... // Is the following syntax possible? BOOST_GENERIC( // Use leading `concept` "keyword" to determine macro functionality.
I considered this during implementation, and same with "auto" concepts, but decided against it for a few reasons. For one, it complicates the implementation for, imo, little or no gain, and it can impact compile-time, which is something that I consider a problem with the library at this point in time.
OK.
// `typename` doesn't need extra parenthesis.
It does if I want to be consistent with all parameter kinds, but I could special-case typename and class if I disallow fully qualified names as you currently do. Right now I support typename/class, value parameters, and soon varidiac parameters which will work via the syntax ( (ParameterKindHere,,,) SomeNameHere ). I'll give some thought to special-casing, but for now, it's more consistent for users and easier to preprocess if I don't do that, and fully qualified names are handled without problem. The more I look at your library though and the more you mention it, the more I question my choice, so it is possible I'll start special-casing things as you are doing, but I have a lot on my plate before I devote time to changing features that already work.
My new syntax also supports these cases: template< class T = int, typename U, T x, int y = 0 > // usual C++ template( class T, default int, typename U, (T) x, int y, default 0 ) // contract syntax If for consistency you want to use extra parenthesis around all types, the following also works: template( class T, default int, typename U, (T) x, (int) y, default 0 )
// `extends` is not necessary but I find it more readable.
This was just because I wanted to use a keyword that an IDE would highlight. In the predecessor to this library I was using words that weren't keywords and Dave Abrahams suggested that I switch over to keywords, with a rationale that I ultimately agreed with (easy to remember, it's not highlighted if you make a typo). Extends is not and likely will not be a keyword in C++.
Also, with concepts, there's no such thing as "private" or "protected" refinement -- the public there acts as "extends" acts in your example in that it's only used to signify that what follows is a list of less refined concepts. If I change it, the public part would just be replaced rather than both words being there, but I'd probably use "refines" instead of extends since that's the proper term in Generic Programming, though that too is not a keyword.
This still keeps public that is highlighted (BTW, in the library docs I will provide the DSEL grammar and a list of the new "keyword" like extends, requires, precondition, etc so you can configure your IDE to color them up) and yes, refines makes more sense: refines( public Semiregular<T> )
// BOOST_GENERIC_ASSIGN just expand to `,` but I find it more readable.
I'm not a big fan of that. I use , because it's short and simple, though I have considered (,) to make it jump out as being different and unambiguous. If you can provide a good rationale for BOOST_GENERIC_ASSIGN over those options, I'm open to it, but at this point I favor simplicitly over a big macro name (and my gut is that most users will too).
, (MoveConstructible) reference BOOST_GENERIC_ASSIGN typename
The encapsulating set of parentheses around each individual parameter are for important reasons. For one, your current example is actually ambiguous.
////////// (MoveConstructible) reference, typename something_here //////////
could either be a contrained typename requirement with a default, or it could be a constrained typename without a default followed by an unconstrained typename. The encapsulating parentheses is imo the simplest solution for users to remember and for implementation, although if I use something like (,) or BOOST_GENERIC_ASSIGN for default assignment I could disambiguate this particular issue that way.
I used ", default ..." for default parameters: (MoveConstructible) reference, default typename x::reference
However, another issue is that the default may, itself, have commas in it. Without the encapsulating parentheses, I can't know if the next comma in a default is a parameter separator or a part of the default (for instance, a default of boost::array< int, 2 >). If I special-case it so that you have the option of wrapping the default in parentheses if it has commas, then it's ambiguous with the situation where there is no default and where the next parameter to the concept macro starts with parentheses, etc. I could keep trying to special-case further, or I could just make a single, consistent rule that's easy to remember as I've done. IMO, this option is simpler for both myself and users and also aids in keeping compile-times down.
To handle unparenthesized commas, I'd use the IDENTITY_TYPE/VALUE macros. Commas not wrapped within parenthesis are rare so IMO it's not worth to ask users to always use extra parenthesis to handle them. It's simpler to ask user to use a special macro when they are present.
Also, since I am consistent with wrapping each parameter with parentheses,
I also went down this path and called the previous syntax "parenthesized syntax" because all tokens were consistently wrapped within extra parenthesis. Then I was think it's easier for users to learn the syntax "just wrap all tokens of the usual C++ syntax within parenthesis (more or less)". Everyone that looked at the syntax complained about the extra parenthesis :(( I also now think that the newer syntax with only a few extra parenthesis is better.
it is much easier for me to give descriptive error reporting if the user screws something up that I can catch at preprocessing time. For instance, if a user is creating a many-line concept, such as an allocator-like concept, and he makes a typo somewhere in the middle, I want to be able to give the best error possible, including a parameter number, that particular parameter text in full, and even be able to continue parsing the remaining parameters to the concept, catching other potential errors during preprocessing. If each parameter is wrapped in parentheses, it is much easier to do this -- any noticeable error that occurs in the middle of a given parameter, even if it involves something tricky like commas, does not affect the parsing of further parameters, and I'm able to output the full parameter text of the parameter with the error in a static assert without accidentally cutting off part of what the user thought was a single parameter but ends up not being the case because of a misplaced comma.
Error reporting is a good point especially because all your code is within the macros (for Boost.Local the function body code is outside the macro and that's were most of the actual programming errors will be so I likely don't have to worry about error reporting too much -- I still check the syntax using the pp as much as possible).
Finally, the concept macro, as I'm sure you can imagine, is fairly nasty underneath the hood. One nice thing about the implementation, however, is that I handle most of the top-level implementation via a simple preprocessor for-each operation over all of the parameters after the name and refinements. Having the parameters consistently separated is what makes this directly possible without any difficulty -- since the parameters are just individual macro arguments, I use a construct that invokes a macro for each parameter. It doesn't require any complicated logic to figure out where individual parameters are separated, is very efficient, and it keeps the loop logic separate from the parsing of individual parameters.
// `operator(symbol, name)` allow user to name the operators
I can't use a symbol, and a user-provided name is unfortunately meaningless both to me and the user here. Associated operator requirements of concepts check if the operator is callable with respect to the pseudo-signature. The reason I use a fixed name is because, internally, I have to generate metafunctions during preprocessing that check to see if the operation is callable for the given parameter types, and what is generated can vary depending on which operator is used. In order to do this, I have to know, entirely during preprocessing, exactly which operator is specified. You can't do this if the user provides the symbol representation of the operator, and an arbitrary, user-specified name wouldn't help. The names I use come from N2914 standard concept names, so there is also some consistency here.
I see.
// Types `X&`, `X&&`, `int`, etc do not need extra parenthesis.
I could special case int and other built-ins, but I don't see how it would be possible to special case X, or X&, etc. The "X" is a user-defined concept parameter for that specific macro invocation, not a universal identifier that I'm using.
, (postincrement_result) operator(++, postinc)( X&, int ) That's a tuple and X& is the only token... why can't you just get it with: PP_VARIADIC_TUPLE_ELEM(0, (X&, int)) // expand to X& I am missing something here... maybe sometimes you have some other tokens like in ( (X&) x, int y ) ??
BOOST_GENERIC( // Use `concept_map` "keyword" to determine macro functionality.
Yes, I can do that, but again, it makes preprocessing more complicated, affects compile-time, and is one more place for a user to make a mistake that I would want to explicitly look for if I were to give an easy-to-read error message. Overall, I don't think I'm gaining enough, if anything, by pushing more stuff into the macro itself. In an ideal world, I agree, that looks cool, but I just don't think it's practical. Simply calling the macro BOOST_GENERIC_CONCEPT_MAP gives me all of the information that I need without additional preprocessing.
// Do you need ObjectType? Is was missing from above syntax...
Sorry, that's covered in the talk itself and is not directly in the slides (the video is not online yet, but I'll link it whenever whoever is doing post uploads it) -- I can't handle concept-constrained concept maps just yet and if it's not clear, ObjectType is a concept as opposed to a type. That's why the example is not exactly the same between the two. In the end, if you are curious, the syntax will be
////////// template( ((ObjectType)) T ) // or if I disallow fully-qualified names template( (concept ObjectType) T ) //////////
, typedef T value_type
, typedef ptrdiff_t difference_type , typedef T& reference , typedef T* pointer
No, that's not really possible in practice. The problem is that the typedefs themselves may contain commas in them and what comes after the comma could potentially be something not parenthesized that is not valid to concatenate with at preprocessing time. I.E. a bool argument with a !, etc. Trying to
Again, can't you use IDENTITY_TYPE to handle unwrapped commas as special cases? That way you simply the syntax removing the extra parenthesis for the common cases (unwrapped commas are rare in my experience).
handle this syntax and do special casing would be complicated and incomplete. Worse, when someone does something that looks as though it should be valid but really is not, solely for preprocessor reasons that I can't explicitly check for such as the one mentioned above, they would get a strange preprocessor concatenation error that would likely be completely meaningless to them. I try hard to make it so that the user should not be seeing errors like that, and without them having to remember what may seem like arbitrary rules that only make sense if you have written something along the lines of this library or your library, or Boost.Parameter, etc. which most programmers have not. Even then, the issues are extremely subtle.
Again, thanks for all of this feedback. I've been wanting another head to kind of tear things apart. If anything, I think I may go ahead and special-case parameters like void, class, typename, etc. though that won't be for a while. Not using a comma as a replacement for = when specifying defaults may happen too. All of the other special-casing and attempted removal of parentheses I'll have to give further thought to, but I think the current design has the least subtle gotchas.
Thanks to you to take a look at Boost.Contract newer syntax. BTW, this is major syntax re-design #4 for Boost.Contract... it requires a lot of patience and perseverance :) --Lorenzo

On Sat, Jun 4, 2011 at 3:37 PM, Lorenzo Caminiti <lorcaminiti@gmail.com>wrote:
This still keeps public that is highlighted (BTW, in the library docs I will provide the DSEL grammar and a list of the new "keyword" like extends, requires, precondition, etc so you can configure your IDE to color them up)
Yeah, I set my IDE to highlight requires as well, as you can see in the slides, but the thing I don't really like about doing it for "extends", is that it's likely not going to be a keyword even in the standard after 0x. So, if someone uses "extends" in their code in a place completely separate from the macro, I think it's not a great idea to have it highlight, otherwise it makes it seem like a user should not be using "extends" as an identifier when in actuality it's perfectly fine. For words like requires, however, since it's very likely that in the next standard it will be a keyword anyway, it's probably a good thing that people see it highlighted now since using it as an identifier will probably break sometime in the next decade (perhaps I'm being optimistic :p).
I used ", default ..." for default parameters:
(MoveConstructible) reference, default typename x::reference
Yeah, I really like your use of default there! I'm going to give it some thought, and I probably will go that route too. To handle unparenthesized commas, I'd use the IDENTITY_TYPE/VALUE
macros. Commas not wrapped within parenthesis are rare so IMO it's not worth to ask users to always use extra parenthesis to handle them. It's simpler to ask user to use a special macro when they are present.
I'm not too sure that I agree with the statement that top-level commas are rare. Templates with multiple parameters aren't that uncommon in the real world, are they? Or am I really out-of-touch with the "real world" here (I admit, this is a possibility, but at least of those who would use a macro library like this, I think it's not that odd)? Either way, if it really is rare, I think I still would rather have the user not have to do anything different when they eventually do write a typedef that contains commas. I like having the corner-cases work with the same syntax as the common case. Error reporting is a good point especially because all your code is
within the macros (for Boost.Local the function body code is outside the macro and that's were most of the actual programming errors will be so I likely don't have to worry about error reporting too much -- I still check the syntax using the pp as much as possible).
Yeah, error reporting at preprocessor time ends up being a huge hassle for me, though I've got it down to a system that's not too difficult to manage now. I've even started checking during preprocessing that associated operators have the correct amount of parameters so that users don't get compile-errors in generated code. , (postincrement_result) operator(++, postinc)( X&, int )
That's a tuple and X& is the only token... why can't you just get it with:
PP_VARIADIC_TUPLE_ELEM(0, (X&, int)) // expand to X&
I am missing something here... maybe sometimes you have some other tokens like in ( (X&) x, int y ) ??
Yup, that's exactly it. The issue is that the user can optionally provide a name for each individual parameter (this is true for all of my parameter lists). So while yes, if a user doesn't provide a name, I can pull out the individual parameter type, but if a name is provided then I can't separate the parameter name from the parameter type, which I need to do underneath the hood. Without the parameter being parenthesized or it being a known name such as int, I can't determine if a parameter name is even there, let alone separate that name from the type.
Thanks to you to take a look at Boost.Contract newer syntax. BTW, this is major syntax re-design #4 for Boost.Contract... it requires a lot of patience and perseverance :)
Yeah, definitely understood! Awesome work. -- -Matt Calabrese

lcaminiti wrote:
I can eliminate a large number of extra parenthesis based on a few pp tricks I've learned in processing Boost.Local's `const bind(type)& var`. Plus, I can provide (optional) support for variadics macros so to use comma-separated pp tuplets instead of parenthesized pp sequences on preprocessors with variadics.
This is "just" a naming question. If you had a macro that returned the trait of the function access level (public, protected, private, or empty), how would you name the macro? For example: PP_META_TRAITS_FUNC_ACCESS( public void (push_back)( (T const&) value ) ) // expand to `public` PP_META_TRAITS_FUNC_ACCESS( void (push_back)( (T const&) value ) ) // expand to nothing I could think to name these trait macros: 1) Meta-programing: PP_META_TRAITS_... 2) Language: PP_LANG_TRAITS_... 3) Syntax: PP_SYN_TRAITS_... 4) Specification: PP_SPEC_TRAITS_... 5) Function, class, template parameters, function parameters, etc: PP_FUNC_TRAITS_... PP_CLASS_TRAITS_..., PP_TEMPLATE_PARAMS_TRAITS_, PP_FUNC_PARAMS_TRAITS_..., etc Also (but I don't like the followings because the trait macros could also return instructions of the function body, class traits, etc so not just function signature, declaration, or definition): 6) Signature: PP_SIGN_TRAITS_... 7) Declaration: PP_DECL_TRAITS_... 8) Definition: PP_DEF_TRAITS_... Do you have an opinion? Thanks a lot. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p356713... Sent from the Boost - Dev mailing list archive at Nabble.com.

lcaminiti wrote:
For example, I _think_ (but I've not implemented this yet) that I can simplify the syntax like this:
#include <contract.hpp> #include <vector> #include "myvector/pushable.hpp"
// Wrapper class that adds contracts to std::vector. CONTRACT_CLASS( template( typename T ) class (myvector) extends( public pushable<T> ) // Subcontracting. ) { CONTRACT_CLASS_INVARIANT( empty() == (size() == 0) // More invariants here (comma separated)... )
CONTRACT_FUNCTION( public void (push_back)( (const T&) element ) precondition( size() < max_size() // More preconditions here (comma separated)... ) postcondition( auto old_size = CONTRACT_OLDOF(size()), // Old value. size() == old_size + 1 // More postconditions here (comma separated)... ) ) { vector_.push_back(element); // Implementation. }
// Rest of the class here (with more contracts if needed)... public: typedef typename std::vector<T>::size_type size_type; size_type size(void) const { return vector_.size(); } size_type max_size(void) const { return vector_.max_size(); } bool empty(void) const { return vector_.empty(); } const T& back(void) const { return vector_.back(); } private: std::vector<T> vector_; };
For a side-by-side comparison with N1962 syntax:
http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/index... For a comparison of the entire std::vector (plus Boost.ConceptCheck concepts):
http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contr... For a comparison for all Boost.Contract features (plus Boost.ConceptCheck concepts and Boost.Parameter named parameters):
http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/contr... (Don't pay attention to the rest of the docs that are way out of date.)
I was able to implement this syntax. If anyone is curious, I have attached the complete grammar of the syntax and the macro APIs to inspect the syntax's meta-traits: http://boost.2283326.n4.nabble.com/file/n3599946/grammar03.cpp grammar03.cpp For example, the macro APIs allow to program the following: #include <contract/detail/preprocessor/traits/func.hpp> #include <boost/preprocessor/facilities/is_empty.hpp> #include <boost/preprocessor/logical/compl.hpp> #define TRAITS_add CONTRACT_DETAIL_PP_FUNC_TRAITS( \ int (add) ( int x, int y ) \ ) #define TRAITS_push_back CONTRACT_DETAIL_PP_FUNC_TRAITS( \ public virtual void (push_back) ( (T&) value ) \ ) #define IS_VIRTUAL(func_traits) \ BOOST_PP_COMPL(BOOST_PP_IS_EMPTY(CONTRACT_DETAIL_PP_FUNC_TRAITS_VIRTUAL( \ func_traits))) IS_VIRTUAL(TRAITS_add) // expand to 0 (not declared virtual) IS_VIRTUAL(TRAITS_push_back) // expand to (declared virtual) #undef TRAITS_add #undef TRAITS_push_back Traits macros source code at: http://contractpp.svn.sourceforge.net/viewvc/contractpp/branches/syn/src/con... --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p359994... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Tue, May 31, 2011 at 2:49 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
I can eliminate a large number of extra parenthesis based on a few pp tricks I've learned in processing Boost.Local's `const bind(type)& var`. Plus, I can provide (optional) support for variadics macros so to use comma-separated pp tuplets instead of parenthesized pp sequences on preprocessors with variadics.
For example, I _think_ (but I've not implemented this yet) that I can simplify the syntax like this:
#include <contract.hpp> #include <vector> #include "myvector/pushable.hpp"
// Wrapper class that adds contracts to std::vector. CONTRACT_CLASS( template( typename T ) class (myvector) extends( public pushable<T> ) // Subcontracting. ) { CONTRACT_CLASS_INVARIANT( empty() == (size() == 0) // More invariants here (comma separated)... )
CONTRACT_FUNCTION( public void (push_back)( (const T&) element ) precondition( size() < max_size() // More preconditions here (comma separated)... ) postcondition( auto old_size = CONTRACT_OLDOF(size()), // Old value. size() == old_size + 1 // More postconditions here (comma separated)... ) ) { vector_.push_back(element); // Implementation. }
// Rest of the class here (with more contracts if needed)... public: typedef typename std::vector<T>::size_type size_type; size_type size(void) const { return vector_.size(); } size_type max_size(void) const { return vector_.max_size(); } bool empty(void) const { return vector_.empty(); } const T& back(void) const { return vector_.back(); } private: std::vector<T> vector_; };
For whomever is curious, I have implemented the new Boost.Contract syntax. Here's large number of examples that now compile with the new syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... Highlights are: * Side-by-side comparison with N1962 (contracts) and N2081 (concepts) syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... * I have also added C++0x-like virtual specifiers (final, override, and new) to Boost.Contract: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... * Side-by-side comparison with Eiffel syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... Comments are always welcome :) (I still have to implement named parameter support (using Boost.Parameter behind the scene) but that shouldn't be too hard. The macros already parse the named parameter syntax using in/out/inout "keywords".) --Lorenzo

on Fri Sep 02 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
For whomever is curious, I have implemented the new Boost.Contract syntax. Here's large number of examples that now compile with the new syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont...
Wow. This is a powerful new language! How does this relate to the work Matt Calabrese started on implementing concepts in C++11 (see the boostcon video)? It looks like this can't possibly be quite right (can it?) http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... Don't you need a comma after "boost::InputIterator<Iter>"?
Highlights are: * Side-by-side comparison with N1962 (contracts) and N2081 (concepts) syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... I have also added C++0x-like virtual specifiers (final, override, and new) to Boost.Contract: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... Side-by-side comparison with Eiffel syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont...
Comments are always welcome :)
* Very impressive! I might even try programming in this language. * How's debuggability (sorry for asking)? * What's a "loop variant?" I've heard of "loop invariants."
(I still have to implement named parameter support (using Boost.Parameter behind the scene) but that shouldn't be too hard. The macros already parse the named parameter syntax using in/out/inout "keywords".)
I can't wait. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Fri, Sep 2, 2011 at 3:14 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Fri Sep 02 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
For whomever is curious, I have implemented the new Boost.Contract syntax. Here's large number of examples that now compile with the new syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont...
Wow. This is a powerful new language! How does this relate to the work
Indeed, Boost.Contract defines a new DSEL which I named L++ ;) Here's the complete grammar (draft): http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... IMO, what is very interesting about L++ when compared with other DSEL (Boost.Phoenix, Boost.Lambda, etc) is that L++ is actually parsed all the way up by the preprocessor. Therefore, L++ can use both preprocessor and template meta-programming to implement it's features (and not "just" template meta-programming). For example, this allows to program the following basic Contract Programming rule: if a member function is not public then it does not check the class invariants This rule cannot be implemented using only template meta-programming because (AFAIK) it is not possible to check if a function is public using a C++ template meta-function like is_public<function-type>. Instead a macro IS_PUBLIC(function-decl) can be written to parse the L++ function declaration and expand to 1 if and only if the function is public: #define IS_PUBLIC(function_decl) ... IS_PUBLIC( public void f ( int x ) ) // expand to 1 IS_PUBLIC( private void g ( int y ) ) // expand to 0
Matt Calabrese started on implementing concepts in C++11 (see the boostcon video)?
Matt and I have exchanged a couple of emails previously on this thread. It looks like we are using similar pp techniques. However, I will have to study Matt's work in more detail before I can really comment...
It looks like this can't possibly be quite right (can it?)
http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont...
Don't you need a comma after "boost::InputIterator<Iter>"?
Yes, I fixed it (I compiled this example with CONTRACT_CONFIG_NO_CONCEPTS which disables concepts so the compiler did not error).
Highlights are: * Side-by-side comparison with N1962 (contracts) and N2081 (concepts) syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... I have also added C++0x-like virtual specifiers (final, override, and new) to Boost.Contract: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... Side-by-side comparison with Eiffel syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont...
Comments are always welcome :)
* Very impressive! I might even try programming in this language. * How's debuggability (sorry for asking)?
After I have implemented the library I have to study: 1) Compile-time overhead (both pp and templates). This could be very significant because the macros use tons of pp code and expand tons of C++ template code. 2) Run-time overhead. This could also be very significant but mainly because of Contract Programming itself. If all contracts are disabled at compile-time that the run-time overhead should instead be 0. 3) Debuggability (integration with gdb, etc). This could be OK. 4) Integration with other tools like Doxygen, IntelliSense, etc. These other tools might simply not work because they might not be able to expand the macros (too complex pp code)... Boost.Wave should work instead...
* What's a "loop variant?" I've heard of "loop invariants."
A loop variant is a non-negative integer expression that monotonically decreases at each iteration of the loop (so it ensures that the loop will terminate because it starts from 100, then 98, then 90, eventually 0 and if less than 0 before the loop terminates the contract is broken because the variant must be >= 0 and the program -- not just the loop :) -- terminates ). http://en.wikipedia.org/wiki/Loop_variant. Eiffel has loop variants, N1962 does not. I implemented them in Boost.Contract but I can't argue they have been very useful for me... http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont...
(I still have to implement named parameter support (using Boost.Parameter behind the scene) but that shouldn't be too hard. The macros already parse the named parameter syntax using in/out/inout "keywords".)
I can't wait.
The grammar for positional, named, and deduced params is here: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... Thanks for your comments! --Lorenzo

On Fri, Sep 2, 2011 at 3:14 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Fri Sep 02 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
(I still have to implement named parameter support (using Boost.Parameter behind the scene) but that shouldn't be too hard. The macros already parse the named parameter syntax using in/out/inout "keywords".)
I can't wait.
Hello all, Here's how I am thinking to support named parameters within Boost.Contract's syntax. Essentially, named (also template) parameters are prefixed by the new preprocessor "keywords" in, out, or in out. Sorry for the large amount of code but these are complex examples from Boost.Parameter docs so you can directly compare this Boost.Contract proposed syntax with the one of Boost.Parameter: http://www.boost.org/doc/libs/1_47_0/libs/parameter/doc/html/index.html namespace graphs { BOOST_PARAMETER_NAME(graph) BOOST_PARAMETER_NAME(visitor) BOOST_PARAMETER_NAME(root_vertex) BOOST_PARAMETER_NAME(index_map) BOOST_PARAMETER_NAME(color_map) CONTRACT_FUNCTION( void (depth_first_search) ( namespace tag, // optional namespace (tag assumed by default) in requires( // requires for type requirements boost::mpl::and_< boost::is_convertible< boost::graph_traits<boost::mpl::_>::traversal_category , boost::indicence_grapth_tag > , boost::is_convertible< boost::graph_traits<boost::mpl::_>::traversal_category , boost::vertex_list_graph_tag > > ) graph, // this is required (because it has no default) in auto visitor, default boost::dfs_visitor<>(), // auto for any type `*` in (typename boost::graph_traits<graphs::graph::_>::vertex_descriptor) root_vertex, default *boost::vertices(graph).first, // with default so optional in requires( boost::mpl::and_< boost::is_integral< boost::property_traits<boost::mpl::_>::value_type > , boost::is_same< typename boost::graph_traits<graphs::graph::_>:: vertex_descriptor , boost::property_traits<boost::mpl::_>::key_type > > ) index_map, default boost::get(boost::vertex_index, graph), in out requires( boost::is_same< typename boost::graph_traits<graphs::graph::_>:: vertex_descriptor , boost::property_traits<boost::mpl::_>::key_type > ) color_map, default default_color_map(boost::num_vertices(graph), index_map) ) precondition(...) postcondition(...) ) { ... } } // namespace graphs And for class templates: namespace py { BOOST_PARAMETER_TEMPLATE_KEYWORD(ClassType) BOOST_PARAMETER_TEMPLATE_KEYWORD(BaseList) BOOST_PARAMETER_TEMPLATE_KEYWORD(HeldType) BOOST_PARAMETER_TEMPLATE_KEYWORD(Copyable) CONTRACT_CLASS( template( in typename ClassType, in typename BaseList, default boost::python::bases<>, in typename HeldType, default ValueType, in typename Copyable, default void ) class (class_) requires(...) // concepts ) { ... // class invariants, members with pre/postconditions, etc }; } // namespace py struct b { virtual ~b() = 0; } struct d : b { ~d(); } typedef py::class_<b, boost::noncopyalbe> c1; typedef py::class_< d, std::auto_ptr<d>, boost::python::bases<b> > c2; IF I can do this (not sure yet), it should be beneficial especially for class templates because all the boiler plate code (class template skeleton A0, A1 = parameter::void_, class template signature, argument pack, and parameter extraction) will be automatically generated by the CONTRACT_CLASS macro. Before I start diving into the implementation, what do you think of this syntax for named parameters? Thanks a lot. --Lorenzo

on Sat Oct 22 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
On Fri, Sep 2, 2011 at 3:14 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Fri Sep 02 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
(I still have to implement named parameter support (using Boost.Parameter behind the scene) but that shouldn't be too hard. The macros already parse the named parameter syntax using in/out/inout "keywords".)
I can't wait.
Hello all,
Here's how I am thinking to support named parameters within Boost.Contract's syntax.
Cool! Don't forget deduced parameters, though ;-)
Essentially, named (also template) parameters are prefixed by the new preprocessor "keywords" in, out, or in out.
Sorry for the large amount of code but these are complex examples from Boost.Parameter docs so you can directly compare this Boost.Contract proposed syntax with the one of Boost.Parameter: http://www.boost.org/doc/libs/1_47_0/libs/parameter/doc/html/index.html
namespace graphs {
BOOST_PARAMETER_NAME(graph) BOOST_PARAMETER_NAME(visitor) BOOST_PARAMETER_NAME(root_vertex) BOOST_PARAMETER_NAME(index_map) BOOST_PARAMETER_NAME(color_map)
CONTRACT_FUNCTION( void (depth_first_search) ( namespace tag, // optional namespace (tag assumed by default)
I'd really like to eliminate that if possible; it's quite off-putting. I guess if you can make it optional, that handles the problem.
in requires( // requires for type requirements
Why are we using "in" before "requires?" Requirements are not "in parameters."
boost::mpl::and_< boost::is_convertible< boost::graph_traits<boost::mpl::_>::traversal_category , boost::indicence_grapth_tag > , boost::is_convertible< boost::graph_traits<boost::mpl::_>::traversal_category , boost::vertex_list_graph_tag > >
I realize this is a direct translation of what's in the Boost.Parameter docs, but it would be instructive to see the example without all the mess, using something like concepts for the "requires" clause. In fact, I believe much of what you have below could also be consolidated into something more semantically meaningful. Would something like that be possible? Also, the use of graphs::graph::_ and boost::mpl::_ below is confusing me. I've never heard of the former. I guess, to sum up, to evaluate the syntax I'd need to see the most beautiful possible realization of this algorithm as opposed to the most horrendous ;-).
And for class templates:
namespace py {
BOOST_PARAMETER_TEMPLATE_KEYWORD(ClassType) BOOST_PARAMETER_TEMPLATE_KEYWORD(BaseList) BOOST_PARAMETER_TEMPLATE_KEYWORD(HeldType) BOOST_PARAMETER_TEMPLATE_KEYWORD(Copyable)
CONTRACT_CLASS( template( in typename ClassType, in typename BaseList, default boost::python::bases<>, in typename HeldType, default ValueType, in typename Copyable, default void ) class (class_) requires(...) // concepts ) { ... // class invariants, members with pre/postconditions, etc };
} // namespace py
struct b { virtual ~b() = 0; } struct d : b { ~d(); }
typedef py::class_<b, boost::noncopyalbe> c1; typedef py::class_< d, std::auto_ptr<d>, boost::python::bases<b> > c2;
This one, again, uses deduced parameters, because as I'm sure you noticed, boost::noncopyable doesn't play the same role as std::auto_ptr<d>. I presume that's possible in your scheme.
IF I can do this (not sure yet), it should be beneficial especially for class templates because all the boiler plate code (class template skeleton A0, A1 = parameter::void_, class template signature, argument pack, and parameter extraction) will be automatically generated by the CONTRACT_CLASS macro.
Before I start diving into the implementation, what do you think of this syntax for named parameters?
Certainly looks nice for the class template case, but as noted above I'm having a hard time digesting the function template example. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Dave Abrahams wrote:
on Sat Oct 22 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
On Fri, Sep 2, 2011 at 3:14 PM, Dave Abrahams <dave@> wrote:
on Fri Sep 02 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
(I still have to implement named parameter support (using Boost.Parameter behind the scene) but that shouldn't be too hard. The macros already parse the named parameter syntax using in/out/inout "keywords".)
I can't wait.
Hello all,
Here's how I am thinking to support named parameters within Boost.Contract's syntax.
Cool! Don't forget deduced parameters, though ;-)
Deduced params will be prefixed by the pp-keyword deduce. For example: CONTRACT_FUNCTION( void (def) ( // skip optional keyword tag namespace in (char const*) name, // input required name with exact type in auto func, // input required function of any type // deduced optional params with exact and predicate type requirement deduce in (char const*) docstring, default "", deduce in requires(is_keyword_expression<_>) keywords, default no_keywords, deduce in requires(not_< or_<is_convertible<_, char const*>, is_keyword_expression<_> > >) policies, default default_call_policies ) precondition( ... ) postcondition( ... ) ) ;
namespace tag, // optional namespace (tag assumed by default)
I'd really like to eliminate that if possible; it's quite off-putting. I guess if you can make it optional, that handles the problem.
Yes, the keyword tag namespace is always optional and tag is used by default (e.g., the python::def above did not specify the namespace).
in requires( // requires for type requirements
Why are we using "in" before "requires?" Requirements are not "in parameters."
This might be tricky... I need to prefix all named parameters with special "keywords" so the pp can distinguish them from positional parameters. In this case, I could just use requires and say that a parameter is named if prefixed by in, out, in out, or requires. However, I need to keep in, out, or in out for exact type requirements (not predicate) because they don't use requires. For example, this is a named parameter: void (f) ( in (typename graph_traits<graph_type>::vertex_descriptor) root_vertex, default *vertices(graph).first, ) But this is a positional parameter (no in prefix): void (f) ( (typename graph_traits<graph_type>::vertex_descriptor) root_vertex, default *vertices(graph).first, ) Can you please explain better why it might be a problem if I always use the in, out, in out specifiers even with predicate type requirements? I'd think ultimately, any parameter must have in, out, or in out semantic even if its type is specified using a metafunction predicate... isn't that ture? For example, depth_first_search documents /all/ its parameters as in, out, or in out: http://www.boost.org/doc/libs/1_47_0/libs/graph/doc/depth_first_search.html
I realize this is a direct translation of what's in the Boost.Parameter docs, but it would be instructive to see the example without all the mess, using something like concepts for the "requires" clause. In fact, I believe much of what you have below could also be consolidated into something more semantically meaningful. Would something like that be possible? Also, the use of graphs::graph::_ and boost::mpl::_ below is confusing me. I've never heard of the former.
I guess, to sum up, to evaluate the syntax I'd need to see the most beautiful possible realization of this algorithm as opposed to the most horrendous ;-).
I understand. Is this version more usable to judge the syntax? #include <contract.hpp> using namespace boost; using namespace boost::mpl::placeholders; using namespace boost::python; namespace graphs { BOOST_PARAMETER_NAME(graph) BOOST_PARAMETER_NAME(visitor) BOOST_PARAMETER_NAME(root_vertex) BOOST_PARAMETER_NAME(index_map) BOOST_PARAMETER_NAME(color_map) // For simplicity, leaving out the use of BOOST_IDENTITY_TYPE for now. CONTRACT_FUNCTION( void (depth_first_search) ( // param keyword tag namespace (always optional, default to `tag`) namespace tag, // input required param with predicate type requirement (requires) in requires(is_incidence_and_vertex_list_graph<_>) graph, // input optional (default) param of any type (auto) in auto visitor, default dfs_visitor<>(), // input optional param with exact type requirement (parenthesized type) in (typename graph_traits<graph_type>::vertex_descriptor) root_vertex, default *vertices(graph).first, // input optional param with predicate type requirement (requires) in requires(is_integral_property_map_of_key<_, typename graph_traits< graph_type>::vertex_descriptor>) index_map, default get(vertex_index, graph), // input-output optional param with predicate type requirement in out requires(is_property_map_of_key<_, typename graph_traits< graph_type>::vertex_descriptor>) color_map, default default_color_map(num_vertices(graph), index_map) ) precondition( ... ) postcondition( ... ) ) ; } // namespace graphs I really appreciate your help on this, I only marginally understand Boost.Parameter. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p393428... Sent from the Boost - Dev mailing list archive at Nabble.com.

on Mon Oct 24 2011, lcaminiti <lorcaminiti-AT-gmail.com> wrote:
Dave Abrahams wrote:
on Sat Oct 22 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
On Fri, Sep 2, 2011 at 3:14 PM, Dave Abrahams <dave@> wrote:
on Fri Sep 02 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
(I still have to implement named parameter support (using Boost.Parameter behind the scene) but that shouldn't be too hard. The macros already parse the named parameter syntax using in/out/inout "keywords".)
I can't wait.
Hello all,
Here's how I am thinking to support named parameters within Boost.Contract's syntax.
Cool! Don't forget deduced parameters, though ;-)
Deduced params will be prefixed by the pp-keyword deduce. For example:
CONTRACT_FUNCTION( void (def) ( // skip optional keyword tag namespace in (char const*) name, // input required name with exact type in auto func, // input required function of any type // deduced optional params with exact and predicate type requirement deduce in (char const*) docstring, default "", deduce in requires(is_keyword_expression<_>) keywords, default no_keywords, deduce in requires(not_< or_<is_convertible<_, char const*>, is_keyword_expression<_> > >) policies, default default_call_policies ) precondition( ... ) postcondition( ... ) ) ;
Nicely done.
namespace tag, // optional namespace (tag assumed by default)
I'd really like to eliminate that if possible; it's quite off-putting. I guess if you can make it optional, that handles the problem.
Yes, the keyword tag namespace is always optional and tag is used by default (e.g., the python::def above did not specify the namespace).
in requires( // requires for type requirements
Why are we using "in" before "requires?" Requirements are not "in parameters."
This might be tricky... I need to prefix all named parameters with special "keywords" so the pp can distinguish them from positional parameters. In this case, I could just use requires and say that a parameter is named if prefixed by in, out, in out, or requires.
Yeah, that's what I was thinking.
However, I need to keep in, out, or in out for exact type requirements (not predicate) because they don't use requires. For example, this is a named parameter:
void (f) ( in (typename graph_traits<graph_type>::vertex_descriptor) root_vertex, default *vertices(graph).first, )
But this is a positional parameter (no in prefix):
void (f) ( (typename graph_traits<graph_type>::vertex_descriptor) root_vertex, default *vertices(graph).first, )
Can you please explain better why it might be a problem if I always use the in, out, in out specifiers even with predicate type requirements?
I'm sorry, maybe I misunderstood. I thought the requires( ... ) clause was not part of a parameter declaration. Ultimately it would probably be syntactically superior if requirements were separated, but if that's not the case I can certainly live with it.
I'd think ultimately, any parameter must have in, out, or in out semantic even if its type is specified using a metafunction predicate... isn't that ture? For example, depth_first_search documents /all/ its parameters as in, out, or in out: http://www.boost.org/doc/libs/1_47_0/libs/graph/doc/depth_first_search.html
Yeah... I think we said at one point that "in" was the default, but that feature may have fallen by the wayside.
I guess, to sum up, to evaluate the syntax I'd need to see the most beautiful possible realization of this algorithm as opposed to the most horrendous ;-).
I understand. Is this version more usable to judge the syntax?
No, it's still too dense because of the comments (and the redundant optional "namespace tag"). Try again, please :-)
#include <contract.hpp>
using namespace boost; using namespace boost::mpl::placeholders; using namespace boost::python;
namespace graphs {
BOOST_PARAMETER_NAME(graph) BOOST_PARAMETER_NAME(visitor) BOOST_PARAMETER_NAME(root_vertex) BOOST_PARAMETER_NAME(index_map) BOOST_PARAMETER_NAME(color_map)
// For simplicity, leaving out the use of BOOST_IDENTITY_TYPE for now. CONTRACT_FUNCTION( void (depth_first_search) ( // param keyword tag namespace (always optional, default to `tag`) namespace tag, // input required param with predicate type requirement (requires) in requires(is_incidence_and_vertex_list_graph<_>) graph, // input optional (default) param of any type (auto) in auto visitor, default dfs_visitor<>(), // input optional param with exact type requirement (parenthesized type) in (typename graph_traits<graph_type>::vertex_descriptor) root_vertex, default *vertices(graph).first, // input optional param with predicate type requirement (requires) in requires(is_integral_property_map_of_key<_, typename graph_traits< graph_type>::vertex_descriptor>) index_map, default get(vertex_index, graph), // input-output optional param with predicate type requirement in out requires(is_property_map_of_key<_, typename graph_traits< graph_type>::vertex_descriptor>) color_map, default default_color_map(num_vertices(graph), index_map) ) precondition( ... ) postcondition( ... ) ) ;
} // namespace graphs
I really appreciate your help on this, I only marginally understand Boost.Parameter. --Lorenzo
-- Dave Abrahams BoostPro Computing http://www.boostpro.com

Dave Abrahams wrote:
on Mon Oct 24 2011, lcaminiti <lorcaminiti-AT-gmail.com> wrote:
Can you please explain better why it might be a problem if I always use the in, out, in out specifiers even with predicate type requirements?
I'm sorry, maybe I misunderstood. I thought the requires( ... ) clause was not part of a parameter declaration. Ultimately it would probably be syntactically superior if requirements were separated, but if that's not the case I can certainly live with it.
Yes, requires* is part of the parameter declaration and it is used to specify the predicate requirement on the parameter type. Note that my library does not add any feature to named parameters that is not already supported by Boost.Parameter (my library simply provides a different syntax for named parameters and then calls the Boost.Parameter macros behind the scene). My library will of course allow to add contracts to the functions and classes with named parameters (but contracts are the "only" added feature). (*) At the end my library will use `requires` in three places: (1) after template... to specify concepts, (2) before a named parameter name to specify the predicate type requirement, and (3) after a contract assertion to specify the assertion requirements. If this is confusing, I could easily use other pp-keywords (in fact, I can use any alphanumeric word I wish) but I think this re-use of requires is just fine and I'll document it well.
No, it's still too dense because of the comments (and the redundant optional "namespace tag"). Try again, please :-)
Sure, that's easy. Let me know if this still requires more work: #include <contract.hpp> using namespace boost; using namespace boost::mpl::placeholders; using namespace boost::python; namespace graphs { BOOST_PARAMETER_NAME(graph) BOOST_PARAMETER_NAME(visitor) BOOST_PARAMETER_NAME(root_vertex) BOOST_PARAMETER_NAME(index_map) BOOST_PARAMETER_NAME(color_map) CONTRACT_FUNCTION( void (depth_first_search) ( in requires(is_incidence_and_vertex_list_graph<_>) graph, in auto visitor, default dfs_visitor<>(), in (typename graph_traits<graph_type>::vertex_descriptor) root_vertex, default *vertices(graph).first, in requires(is_integral_property_map_of_key<_, typename graph_traits< graph_type>::vertex_descriptor>) index_map, default get(vertex_index, graph), in out requires(is_property_map_of_key<_, typename graph_traits< graph_type>::vertex_descriptor>) color_map, default default_color_map(num_vertices(graph), index_map) ) precondition( ... ) postcondition( ... ) ) { ... } } // namespace graphs namespace py { CONTRACT_FUNCTION( void (def) ( in (char const*) name, in auto func, deduce in (char const*) docstring, default "", deduce in requires(is_keyword_expression<_>) keywords, default no_keywords, deduce in requires(not_< or_<is_convertible<_, char const*>, is_keyword_expression<_> > >) policies, default default_call_policies ) precondition( ... ) postcondition( ... ) ) { ... } } // namespace py What do you think? --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p393488... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Mon, Oct 24, 2011 at 7:01 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
Dave Abrahams wrote:
No, it's still too dense because of the comments (and the redundant optional "namespace tag"). Try again, please :-) Sure, that's easy. Let me know if this still requires more work:
For template parameters: namespace py { BOOST_PARAMETER_TEMPLATE_KEYWORD(ClassType) BOOST_PARAMETER_TEMPLATE_KEYWORD(BaseList) BOOST_PARAMETER_TEMPLATE_KEYWORD(HeldType) BOOST_PARAMETER_TEMPLATE_KEYWORD(Copyable) CONTRACT_CLASS( template( in requires(is_class<_>) ClassType, in requires(is_sequence<_>) BaseList, default bases<>, in class HeldType, default ClassType, in typename Copyable, default void ) class (class_) requires( ... ) // concepts ) { ... // declarations with class invariants, preconditions, postconditions }; } // namespace py typedef py::class_< py::ClassType<B>, py::Copyable<noncopyable> > c1; typedef py::class_< D, py::HeldType< auto_ptr<D> >, py::BaseList< bases<B> > > c2; As you can see the syntax is exactly the same as for function parameters (see quoted text below) with the exception of using typename or class instead of auto for a parameter without any requirement. Similarly, for deduced template parameters: namespace py { BOOST_PARAMETER_TEMPLATE_KEYWORD(ClassType) BOOST_PARAMETER_TEMPLATE_KEYWORD(BaseList) BOOST_PARAMETER_TEMPLATE_KEYWORD(HeldType) BOOST_PARAMETER_TEMPLATE_KEYWORD(Copyable) CONTRACT_CLASS( template( in requires(is_class<_>) ClassType, deduce in requires(is_base_and_derived<detail::bases_base, _>) BaseList, default bases<>, deduce in requires(not_< or_< is_base_and_derived<detail::bases:base, _>, is_same<noncopyable, _> > >) HeldType, default ClassType, deduce in requires(is_same<noncopyable, _>) Copyable, default void ) class (class_) requires( ... ) // concepts ) { ... // declarations with class invariants, preconditions, postconditions }; } // namespace py typedef py::class_< B, noncoyable > d1; typedef py::class_< D, auto_ptr<D>, bases<B> > d2; These macros should be able to automatically generate all needed Boost.Parameter code (template skeleton, signature, binding, and parameter typedefs).
#include <contract.hpp>
using namespace boost; using namespace boost::mpl::placeholders; using namespace boost::python;
namespace graphs {
BOOST_PARAMETER_NAME(graph) BOOST_PARAMETER_NAME(visitor) BOOST_PARAMETER_NAME(root_vertex) BOOST_PARAMETER_NAME(index_map) BOOST_PARAMETER_NAME(color_map)
CONTRACT_FUNCTION( void (depth_first_search) ( in requires(is_incidence_and_vertex_list_graph<_>) graph, in auto visitor, default dfs_visitor<>(), in (typename graph_traits<graph_type>::vertex_descriptor) root_vertex, default *vertices(graph).first, in requires(is_integral_property_map_of_key<_, typename graph_traits< graph_type>::vertex_descriptor>) index_map, default get(vertex_index, graph), in out requires(is_property_map_of_key<_, typename graph_traits< graph_type>::vertex_descriptor>) color_map, default default_color_map(num_vertices(graph), index_map) ) precondition( ... ) postcondition( ... ) ) { ... }
} // namespace graphs
namespace py {
CONTRACT_FUNCTION( void (def) ( in (char const*) name, in auto func, deduce in (char const*) docstring, default "", deduce in requires(is_keyword_expression<_>) keywords, default no_keywords, deduce in requires(not_< or_<is_convertible<_, char const*>, is_keyword_expression<_> > >) policies, default default_call_policies ) precondition( ... ) postcondition( ... ) ) { ... }
} // namespace py
What do you think?
--Lorenzo

On Tue, Oct 25, 2011 at 11:35 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Mon, Oct 24, 2011 at 7:01 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
Dave Abrahams wrote:
No, it's still too dense because of the comments (and the redundant optional "namespace tag"). Try again, please :-) Sure, that's easy. Let me know if this still requires more work:
I re-wrote all examples from Boost.Parameter using the proposed Boost.Contract syntax for named parameters (these named parameter examples don't compile yet): https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont... With named parameters for templates and constructors, Boost.Contract should be able to save the programmer from some boiler-plate code required instead by Boost.Parameter: https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont... https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont... This additional example mixes a bit more named parameters and contracts: https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont... Comments are always welcome :) --Lorenzo

On Sun, Nov 6, 2011 at 9:31 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Tue, Oct 25, 2011 at 11:35 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Mon, Oct 24, 2011 at 7:01 PM, lcaminiti <lorcaminiti@gmail.com> wrote:
Dave Abrahams wrote:
No, it's still too dense because of the comments (and the redundant optional "namespace tag"). Try again, please :-) Sure, that's easy. Let me know if this still requires more work:
I re-wrote all examples from Boost.Parameter using the proposed Boost.Contract syntax for named parameters (these named parameter examples don't compile yet):
https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont...
With named parameters for templates and constructors, Boost.Contract should be able to save the programmer from some boiler-plate code required instead by Boost.Parameter:
https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont... https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont...
This additional example mixes a bit more named parameters and contracts:
https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont...
Comments are always welcome :)
--Lorenzo
The following turned out to be a decent example that uses together a bit of all the different features (contracts, concepts, and named parameters) so I decided to cut-n-paste it here in an email: #include <contract.hpp> #include <boost/concept_check.hpp> #include <boost/type_traits/has_equal_to.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/long.hpp> #include <boost/mpl/char.hpp> #include <iostream> namespace num { namespace tag // Namespace `tag` already used here, use `keywords` instead. { typedef int Value; // Dummy declarations... typedef boost::mpl::int_<1> Default; Value value = Default::value; } // Also use `Param` and `_param` postfixes instead of `_` prefix. CONTRACT_TEMPLATE_PARAMETER((ValueParam, keywords) Value) CONTRACT_TEMPLATE_PARAMETER((DefaultParam, keywords) Default) CONTRACT_PARAMETER((value_param, keywords) value) CONTRACT_CLASS( template( // Named parameters. namespace keywords, // Use namespace `keywords` instead of `tag`. in typename Value, default int, in requires(is_same<boost::mpl::_::type, Value>) Default, default boost::mpl::int_<1> ) requires( boost::Copyable<Value> ) // Concepts. struct (positive) ) { CONTRACT_CLASS_INVARIANT_TPL( // Contracts. static class( static_assert(Default::value > 0, "positive default value") ), get() > 0 ) CONTRACT_CONSTRUCTOR_TPL( public (positive) ( void ) initialize( value_(Default::value) ) ) {} CONTRACT_FUNCTION_TPL( public void (set) ( namespace keywords, in (Value const&) value ) precondition( value > 0 ) postcondition( get() == value, requires boost::has_equal_to<Value>::value ) ) { value_ = value; } CONTRACT_FUNCTION_TPL( public (Value const&) (get) ( void ) const ) { return value_; } private: Value value_; }; } // namespace num int main ( void ) { num::positive< char, boost::mpl::char_<'z'> > p; num::positive< > q; // Use `...Param` instead of `_...`. num::positive< num::DefaultParam< boost::mpl::int_<10> > > r; num::positive< num::DefaultParam< boost::mpl::long_<10> > , num::ValueParam<long> > s; std::cout << s.get() << std::endl; s.set(num::value_param = 123); // Use `..._param` instead of `_...`. std::cout << s.get() << std::endl; return 0; } The goal here is to use Boost.Contract to /completely/ specify the interface for the positive abstract data type. --Lorenzo

on Tue Nov 08 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
The following turned out to be a decent example that uses together a bit of all the different features (contracts, concepts, and named parameters) so I decided to cut-n-paste it here in an email:
#include <contract.hpp> #include <boost/concept_check.hpp> #include <boost/type_traits/has_equal_to.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/long.hpp> #include <boost/mpl/char.hpp> #include <iostream>
namespace num {
namespace tag // Namespace `tag` already used here, use `keywords` instead. { typedef int Value; // Dummy declarations... typedef boost::mpl::int_<1> Default; Value value = Default::value; }
The point of the above is just to have an excuse to use the "namespace" option below? I would leave this out of the example (and leave out that option); it's not useful to show corner-case handling like this in early examples.
// Also use `Param` and `_param` postfixes instead of `_` prefix. CONTRACT_TEMPLATE_PARAMETER((ValueParam, keywords) Value) CONTRACT_TEMPLATE_PARAMETER((DefaultParam, keywords) Default) CONTRACT_PARAMETER((value_param, keywords) value)
Ditto, I think.
CONTRACT_CLASS( template( // Named parameters. namespace keywords, // Use namespace `keywords` instead of `tag`. in typename Value, default int,
I presume this is essentially "typename Value=int". I don't love separating one argument with a comma that way. Would in typename (Value, int) or something similar be practical?
in requires(is_same<boost::mpl::_::type, Value>) Default, default boost::mpl::int_<1>
I don't understand what this is supposed to be saying. Could you explain it? Have you thought of using decltype in the implementation, to avoid writing ::type up there? Something like boost::mpl::_::type seems like maybe it should be spelled "auto" (if possible).
) requires( boost::Copyable<Value> ) // Concepts. struct (positive) ) { CONTRACT_CLASS_INVARIANT_TPL( // Contracts.
Why is that a better spelling than CONTRACT_CLASS_TPL_INVARIANT?
static class( static_assert(Default::value > 0, "positive default value") ),
I don't understand what the "static class(...)" construct is doing here.
get() > 0 )
CONTRACT_CONSTRUCTOR_TPL( public (positive) ( void )
Is "void" mandatory here?
initialize( value_(Default::value) ) ) {}
What is "value_"?
CONTRACT_FUNCTION_TPL( public void (set) ( namespace keywords, in (Value const&) value ) precondition( value > 0 ) postcondition( get() == value, requires boost::has_equal_to<Value>::value
Why must ::value appear in the previous line?
) ) { value_ = value; }
CONTRACT_FUNCTION_TPL( public (Value const&) (get) ( void ) const ) { return value_; }
private: Value value_; };
} // namespace num
int main ( void ) { num::positive< char, boost::mpl::char_<'z'> > p; num::positive< > q;
// Use `...Param` instead of `_...`. num::positive< num::DefaultParam< boost::mpl::int_<10> > > r; num::positive< num::DefaultParam< boost::mpl::long_<10> > , num::ValueParam<long> > s;
std::cout << s.get() << std::endl; s.set(num::value_param = 123); // Use `..._param` instead of `_...`. std::cout << s.get() << std::endl;
return 0; }
The goal here is to use Boost.Contract to /completely/ specify the interface for the positive abstract data type.
This is very nice, but still could use some explanation and simplification. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Tue, Nov 8, 2011 at 2:07 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Tue Nov 08 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
The following turned out to be a decent example that uses together a bit of all the different features (contracts, concepts, and named parameters) so I decided to cut-n-paste it here in an email:
#include <contract.hpp> #include <boost/concept_check.hpp> #include <boost/type_traits/has_equal_to.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/long.hpp> #include <boost/mpl/char.hpp> #include <iostream>
namespace num {
namespace tag // Namespace `tag` already used here, use `keywords` instead. { typedef int Value; // Dummy declarations... typedef boost::mpl::int_<1> Default; Value value = Default::value; }
The point of the above is just to have an excuse to use the "namespace" option below? I would leave this out of the example (and leave out that option); it's not useful to show corner-case handling like this in early examples.
Yes, it's just an excuse to use a namespace different than tag. I am now using these examples to design the library so I want them to exercise all the different features. In the library docs, I will probably use different/modified examples and I will make sure to not confuse the users with the namespace stuff (I'll only mention it in the Advanced Section).
// Also use `Param` and `_param` postfixes instead of `_` prefix. CONTRACT_TEMPLATE_PARAMETER((ValueParam, keywords) Value) CONTRACT_TEMPLATE_PARAMETER((DefaultParam, keywords) Default) CONTRACT_PARAMETER((value_param, keywords) value)
Ditto, I think.
Yes, same as for namespace (there to exercise the feature and I'll document it only for advanced usages).
CONTRACT_CLASS( template( // Named parameters. namespace keywords, // Use namespace `keywords` instead of `tag`. in typename Value, default int,
I presume this is essentially "typename Value=int". I don't love separating one argument with a comma that way. Would
in typename (Value, int) or something similar be practical?
No because my syntax also supports non-variadic compilers and the above will have to become (Value)(int) which forces extra parenthesis around (Value) even when there is no default. `..., default ...` is consistently used to indicate default parameter value (template or functional) and in my experience you get used to it pretty quickly. In fact, I personally prefer Value, default int to (Value, int) (because in the second there is no description of the semantic of the 2nd token int).
in requires(is_same<boost::mpl::_::type, Value>) Default, default boost::mpl::int_<1>
I don't understand what this is supposed to be saying. Could you explain it?
This is a way of passing a named value template parameter by wrapping within a type template parameter as you suggested... is there a better way to do this? I want to pass: template< typename Value, Value default_value = 1 > Where both Value and default_value are named using Boost.Parameter.
Have you thought of using decltype in the implementation, to avoid writing ::type up there?
I'm not using C++1 features. (The C++11-looking auto, static_assert, etc that you see in Boost.Contract are all handled by the pp and implemented using C++03.)
Something like boost::mpl::_::type seems like maybe it should be spelled "auto" (if possible).
It cannot because it is nested inside the named parameter type predicate so the pp has to way to parse it. ::type is needed because I am using a type to wrap a value so the value template parameter can be named (as indicated above).
) requires( boost::Copyable<Value> ) // Concepts. struct (positive) ) { CONTRACT_CLASS_INVARIANT_TPL( // Contracts.
Why is that a better spelling than CONTRACT_CLASS_TPL_INVARIANT?
static class( static_assert(Default::value > 0, "positive default value") ),
I don't understand what the "static class(...)" construct is doing here.
This will be detailed in Boost.Contract docs (it's an addition over N1962). All assertions within static class(...) specify /static class invariants/. (Non-static) class invariants are not checked at entry/exit of static functions or at constructor entry. However, static class invariants are also checked at entry/exit of static functions and at constructor entry. Obviously, static class invaraints cannot refer to the object (but only to static member data/functions). In addition, this one static class invariant is using a static assertion (for this example, given that the assertion is static it could also have been programmed as part of the non-static class invariants and get the same type of checking which is always at compile-time for static_assert). Static class invariants were discussed with N1962 authors 1+ years ago over the Boost ML (no one had objections on them but no one seemed to think they will be useful in real life).
get() > 0 )
CONTRACT_CONSTRUCTOR_TPL( public (positive) ( void )
Is "void" mandatory here?
No if your compiler supports empty macro parameters or variadics. However, often MSVC (which in theory supports both) gets confused and generates pp-error. So I always use void to indicate and empty (parameter) list so the code is most portable.
initialize( value_(Default::value) ) ) {}
What is "value_"?
A private member variable.
CONTRACT_FUNCTION_TPL( public void (set) ( namespace keywords, in (Value const&) value ) precondition( value > 0 ) postcondition( get() == value, requires boost::has_equal_to<Value>::value
Why must ::value appear in the previous line?
Because assertion requirements are specified using integral static constants and not nullary metafunctions. This could be (esaily) changed to be more consistent with named parameter requires that uses unary metafunctions... I'll think about it.
) ) { value_ = value; }
CONTRACT_FUNCTION_TPL( public (Value const&) (get) ( void ) const ) { return value_; }
private: Value value_; };
} // namespace num
int main ( void ) { num::positive< char, boost::mpl::char_<'z'> > p; num::positive< > q;
// Use `...Param` instead of `_...`. num::positive< num::DefaultParam< boost::mpl::int_<10> > > r; num::positive< num::DefaultParam< boost::mpl::long_<10> > , num::ValueParam<long> > s;
std::cout << s.get() << std::endl; s.set(num::value_param = 123); // Use `..._param` instead of `_...`. std::cout << s.get() << std::endl;
return 0; }
The goal here is to use Boost.Contract to /completely/ specify the interface for the positive abstract data type.
This is very nice, but still could use some explanation and simplification.
Explanation will definitely go in the docs. What simplifications would you suggest? Thanks a lot :) --Lorenzo

on Tue Nov 08 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
I presume this is essentially "typename Value=int". I don't love separating one argument with a comma that way. Would
in typename (Value, int) or something similar be practical?
No because my syntax also supports non-variadic compilers
Oh!
and the above will have to become (Value)(int) which forces extra parenthesis around (Value) even when there is no default. `..., default ...` is consistently used to indicate default parameter value (template or functional) and in my experience you get used to it pretty quickly.
I don't mind "default" at all, but the fact that it is separated by a comma from "in typename Value", with no grouping to distinguish that comma from the commas that separate parameters, is ugly. If it's the only way to make it work, then so be it, but I'd prefer to have the default value grouped somehow with the parameter name.
In fact, I personally prefer Value, default int to (Value, int) (because in the second there is no description of the semantic of the 2nd token int).
in requires(is_same<boost::mpl::_::type, Value>) Default, default boost::mpl::int_<1>
I don't understand what this is supposed to be saying. Could you explain it?
This is a way of passing a named value template parameter by wrapping within a type template parameter as you suggested...
Well, it may be, but I don't understand how it works.
is there a better way to do this? I want to pass:
template< typename Value, Value default_value = 1 >
Where both Value and default_value are named using Boost.Parameter.
If I were you I would try to think a little beyond the limitations of Boost.Parameter. If there's an interface we can implement that better supports this use-case, we'll add it. Is there?
Have you thought of using decltype in the implementation, to avoid writing ::type up there?
I'm not using C++1 features. (The C++11-looking auto, static_assert, etc that you see in Boost.Contract are all handled by the pp and implemented using C++03.)
Wow! But decltype might be (a little) different, since we can emulate it with Boost.Typeof. Just something to consider.
Something like boost::mpl::_::type seems like maybe it should be spelled "auto" (if possible).
It cannot because it is nested inside the named parameter type predicate so the pp has to way to parse it.
Right. Well, boost::contract::auto_ then? I know, yuck :-P
::type is needed because I am using a type to wrap a value so the value template parameter can be named (as indicated above).
I don't understand what you're saying here yet.
) requires( boost::Copyable<Value> ) // Concepts. struct (positive) ) { CONTRACT_CLASS_INVARIANT_TPL( // Contracts.
Because it's an invariant for a class template, not an invariant template. At least, IIUC.
Why is that a better spelling than CONTRACT_CLASS_TPL_INVARIANT?
static class( static_assert(Default::value > 0, "positive default value") ),
I don't understand what the "static class(...)" construct is doing here.
This will be detailed in Boost.Contract docs (it's an addition over N1962). All assertions within static class(...) specify /static class invariants/. (Non-static) class invariants are not checked at entry/exit of static functions or at constructor entry. However, static class invariants are also checked at entry/exit of static functions and at constructor entry.
Hm, OK.
Obviously, static class invaraints cannot refer to the object (but only to static member data/functions). In addition, this one static class invariant is using a static assertion (for this example, given that the assertion is static it could also have been programmed as part of the non-static class invariants and get the same type of checking which is always at compile-time for static_assert).
[OK. It would be good to have an example in the end product that doesn't include that kind of redundancy.]
Static class invariants were discussed with N1962 authors 1+ years ago over the Boost ML (no one had objections on them but no one seemed to think they will be useful in real life).
In that case, I think you should omit them. Premature generalization is the root of all evil ;-)
get() > 0 )
CONTRACT_CONSTRUCTOR_TPL( public (positive) ( void )
Is "void" mandatory here?
No if your compiler supports empty macro parameters or variadics. However, often MSVC (which in theory supports both) gets confused and generates pp-error. So I always use void to indicate and empty (parameter) list so the code is most portable.
Ah.
initialize( value_(Default::value) ) ) {}
What is "value_"?
A private member variable.
OK, thanks.
CONTRACT_FUNCTION_TPL( public void (set) ( namespace keywords, in (Value const&) value ) precondition( value > 0 ) postcondition( get() == value, requires boost::has_equal_to<Value>::value
Why must ::value appear in the previous line?
Because assertion requirements are specified using integral static constants and not nullary metafunctions. This could be (esaily) changed to be more consistent with named parameter requires that uses unary metafunctions... I'll think about it.
Please do.
This is very nice, but still could use some explanation and simplification.
Explanation will definitely go in the docs. What simplifications would you suggest?
E.g. leaving out the "namespace" stuff and the features that nobody thinks will be useful. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Tue, Nov 8, 2011 at 10:35 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Tue Nov 08 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
I presume this is essentially "typename Value=int". I don't love separating one argument with a comma that way. Would
in typename (Value, int) or something similar be practical?
No because my syntax also supports non-variadic compilers
Oh!
and the above will have to become (Value)(int) which forces extra parenthesis around (Value) even when there is no default. `..., default ...` is consistently used to indicate default parameter value (template or functional) and in my experience you get used to it pretty quickly.
I don't mind "default" at all, but the fact that it is separated by a comma from "in typename Value", with no grouping to distinguish that comma from the commas that separate parameters, is ugly. If it's the only way to make it work, then so be it, but I'd prefer to have the default value grouped somehow with the parameter name.
The following can be done: #define WITH_DEFAULT , default template( typename T, typename U WITH_DEFAULT int ) // (1) Anyway, I can see why (1) seems more natural at first but after using the syntax my experience really is that `typename U, default int` is just as good (actually better because less cryptic). (For non variadic compilers `#define WITH_DEFAULT )(default`.)
In fact, I personally prefer Value, default int to (Value, int) (because in the second there is no description of the semantic of the 2nd token int).
in requires(is_same<boost::mpl::_::type, Value>) Default, default boost::mpl::int_<1>
I don't understand what this is supposed to be saying. Could you explain it?
This is a way of passing a named value template parameter by wrapping within a type template parameter as you suggested...
Well, it may be, but I don't understand how it works.
In "normal" C++, I want to do: typename< typename Value = int , Value default_value = 1
But I can only use type template parameters (because of Boost.Parameter limitations) so I do: typename< typename Value = int , typename Default = mpl::int_<1>
With the requirement (not yet programmed) that Default::type == Value. In Boost.Contract syntax, it becomes: typename( in typename Value, default int , in requires(is_same<typename mpl::_::type, Value>) Default, default mpl::int_<1> // (2) )
is there a better way to do this? I want to pass:
template< typename Value, Value default_value = 1 >
Where both Value and default_value are named using Boost.Parameter.
If I were you I would try to think a little beyond the limitations of Boost.Parameter. If there's an interface we can implement that better supports this use-case, we'll add it. Is there?
OK. The Boost.Contract syntax itself can do this following the same conventions we discussed for function parameters. In "normal" C++": template< typename Value = int , Value default_value = 1
In an hypothetical C++ with named parameters, it'd become (just prefix the parameters with `in`): template< in typename Value = int , in Value default_value = 1
Now in Boost.Contract syntax, it becomes (replace <> with (), wrap user and qualified types within extra parenthesis, and use default instead of =): template( in typename Value, default int , in (Value) default_value, default 1 ) The syntax itself would support this representation of value template parameters however then I cannot use Boost.Parameter behind the scenes to implement it. Therefore, with the workaround of using the int_ type instead of the int value for the default-value template parameter, it becomes: typename( in typename Value, default int , in requires(is_same<typename mpl::_::type, Value>) Default, default mpl::int_<1> )
Have you thought of using decltype in the implementation, to avoid writing ::type up there?
I'm not using C++1 features. (The C++11-looking auto, static_assert, etc that you see in Boost.Contract are all handled by the pp and implemented using C++03.)
Wow! But decltype might be (a little) different, since we can emulate it with Boost.Typeof. Just something to consider.
Yes, I do use Boost.Typeof (that's how auto is implemented by the macro expansion after being parsed by the pp).
Something like boost::mpl::_::type seems like maybe it should be spelled "auto" (if possible).
It cannot because it is nested inside the named parameter type predicate so the pp has to way to parse it.
Right. Well, boost::contract::auto_ then? I know, yuck :-P
I'm not sure. The point is that mpl::_ is an int_, char_, long_, etc in this case and I want to express the constraint int_::type == Value, char_::type == Value, etc as explained in (2) above. Therefore, I think the use of mpl::_::type is consistent with using unary metafunctions to express named parameter type requirements. Note that I just learned yesterday that type expressions need all to be evaluated lazily with Boost.Parameter type requirements so ::type will not actually work here. I will have to go via another metafunction like: template< typename F, typename T > struct is_same_type : is_same< typename F::type, T > {}; typename( in typename Value, default int , in requires(is_same_type<mpl::_, Value>) Default, default mpl::int_<1> )
::type is needed because I am using a type to wrap a value so the value template parameter can be named (as indicated above).
I don't understand what you're saying here yet.
Was I able to clarify this with the examples above?
) requires( boost::Copyable<Value> ) // Concepts. struct (positive) ) { CONTRACT_CLASS_INVARIANT_TPL( // Contracts.
Because it's an invariant for a class template, not an invariant template. At least, IIUC.
Why is that a better spelling than CONTRACT_CLASS_TPL_INVARIANT?
Sorry I forgot to address this. The _TPL postfix is added to the contract macros when they are used within a template. So all CONTRACT_CLASS_INVARIANT, CONTRACT_FUNCTION, CONTRACT_CONSTRUCTOR, etc become CONTRACT_CLASS_INVARIANT_TPL, CONTRACT_FUNCTION_TPL, CONTRACT_CONSTRUCTOR_TPL, etc when the enclosing class is a template. Rationale. This is needed because C++03 doesn't allow to use typename freely outside templates :( There is actually a mechanism that I can use to not require the _TPL postfix but it relies on making /all/ functions generated by the contract macros function templates and therefore it increases compilation time so I preferred to ask the user to say when the enclosing scope is a template by specifying the _TPL postfix.
static class( static_assert(Default::value > 0, "positive default value") ),
I don't understand what the "static class(...)" construct is doing here.
This will be detailed in Boost.Contract docs (it's an addition over N1962). All assertions within static class(...) specify /static class invariants/. (Non-static) class invariants are not checked at entry/exit of static functions or at constructor entry. However, static class invariants are also checked at entry/exit of static functions and at constructor entry.
Hm, OK.
Obviously, static class invaraints cannot refer to the object (but only to static member data/functions). In addition, this one static class invariant is using a static assertion (for this example, given that the assertion is static it could also have been programmed as part of the non-static class invariants and get the same type of checking which is always at compile-time for static_assert).
[OK. It would be good to have an example in the end product that doesn't include that kind of redundancy.]
Static class invariants were discussed with N1962 authors 1+ years ago over the Boost ML (no one had objections on them but no one seemed to think they will be useful in real life).
In that case, I think you should omit them. Premature generalization is the root of all evil ;-)
I'd like to leave them. I tough about it for a while and I want to be bold in suggesting both static and volatile class invariants because I think they make sense for Contract Programming in C++. I will of course have to document my reasons for the "addition" to these feature well. The main point is that contracts should cover and integrate with /all/ C++ features (which are many and diverse). Static and volatile class invariants are an example of this. Another example are assertion requirements (also not part of N1962) that can be used to handle the outstanding case of types with a copy constructor but without an operator==. The generalization principle here is not to add "extra" features for contracts, it is instead for contracts to cover all existing C++ features (static and volatile members included).
get() > 0 )
CONTRACT_CONSTRUCTOR_TPL( public (positive) ( void )
Is "void" mandatory here?
No if your compiler supports empty macro parameters or variadics. However, often MSVC (which in theory supports both) gets confused and generates pp-error. So I always use void to indicate and empty (parameter) list so the code is most portable.
Ah.
initialize( value_(Default::value) ) ) {}
What is "value_"?
A private member variable.
OK, thanks.
CONTRACT_FUNCTION_TPL( public void (set) ( namespace keywords, in (Value const&) value ) precondition( value > 0 ) postcondition( get() == value, requires boost::has_equal_to<Value>::value
Why must ::value appear in the previous line?
Because assertion requirements are specified using integral static constants and not nullary metafunctions. This could be (esaily) changed to be more consistent with named parameter requires that uses unary metafunctions... I'll think about it.
Please do.
Why would you prefer the assertion requirement to be a nullary metafunction instead than a integral static constant? One reason now is because named parameter type requirements are (unary) metafunctions but I am sincerely asking if there are other good reasons for this.
This is very nice, but still could use some explanation and simplification.
Explanation will definitely go in the docs. What simplifications would you suggest?
E.g. leaving out the "namespace" stuff and the features that nobody thinks will be useful.
OK, let me try again: #include <contract.hpp> #include <boost/concept_check.hpp> #include <boost/type_traits/has_equal_to.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/char.hpp> #include <boost/mpl/long.hpp> #include <iostream> namespace num { template< typename F, typename T > struct is_same_type : boost::is_same<typename F::type, T> {}; CONTRACT_TEMPLATE_PARAMETER(Value) CONTRACT_TEMPLATE_PARAMETER(Default) CONTRACT_PARAMETER(value) CONTRACT_CLASS( template( // Named parameters. in typename Value, default int, in requires(is_same_type<boost::mpl::_, Value>) Default, default boost::mpl::int_<1> ) requires( boost::Copyable<Value> ) // Concepts. struct (positive) ) { CONTRACT_CLASS_INVARIANT_TPL( // Contracts. static_assert(Default::value > 0, "positive default value"), get() > 0 ) CONTRACT_CONSTRUCTOR_TPL( public (positive) ( void ) initialize( value_(Default::value) ) ) {} CONTRACT_DESTRUCTOR_TPL( public (~positive) ( void ) ) {} CONTRACT_FUNCTION_TPL( public void (set) ( in (Value const&) value ) // Named parameter. precondition( value > 0 ) postcondition( get() == value, requires boost::has_equal_to<Value>::value ) ) { value_ = value; } CONTRACT_FUNCTION_TPL( public (Value const&) (get) ( void ) const ) { return value_; } private: Value value_; }; } // namespace num int main ( void ) { num::positive< char, boost::mpl::char_<'z'> > p; num::positive< > q; num::positive< num::_Default< boost::mpl::int_<10> > > r; num::positive< num::_Default< boost::mpl::long_<10> > , num::_Value<long> > s; std::cout << s.get() << std::endl; s.set(num::_value = 123); std::cout << s.get() << std::endl; return 0; }
The goal here is to use Boost.Contract to /completely/ specify the interface for the positive abstract data type.
Thanks! --Lorenzo

On Wed, Nov 9, 2011 at 6:16 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
The goal here is to use Boost.Contract to /completely/ specify the interface for the positive abstract data type.
For whomever is curious, the Boost.Contract named and deduced parameter examples now compile: https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont... Here's an example that uses a bit of everything: Contracts, concepts, named/deduced function and template parameters: #include <boost/python.hpp> #include <contract.hpp> #include <contract/parameter.hpp> // For named parameters. #include <contract/concept.hpp> // For concepts. #include <boost/concept_check.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/not.hpp> #include <boost/mpl/or.hpp> #include <boost/shared_ptr.hpp> #include <boost/noncopyable.hpp> #include <boost/regex.hpp> namespace py { // Helpers. bool is_identifier ( char const* name ) { static const boost::regex re("(\\l|\\u|_)(\\l|\\u|\\d|_)*"); return boost::regex_match(name, re); } // Class template with named parameters. CONTRACT_TEMPLATE_PARAMETER(ClassType) CONTRACT_TEMPLATE_PARAMETER(Bases) CONTRACT_TEMPLATE_PARAMETER(HeldType) CONTRACT_TEMPLATE_PARAMETER(Copyable) CONTRACT_PARAMETER(name) CONTRACT_CLASS( template( // Required named template parameter. in typename requires(boost::is_class<boost::mpl::_>) ClassType, // Deduced and optional named template parameters with type requirements. deduce in typename requires(boost::python::detail::specifies_bases< boost::mpl::_>) Bases, default boost::python::bases<>, deduce in typename requires(BOOST_IDENTITY_TYPE((boost::mpl::not_< boost::mpl::or_< boost::python::detail::specifies_bases<boost::mpl::_> , boost::is_same<boost::noncopyable, boost::mpl::_> > >))) HeldType, default boost::python::detail::not_specified, deduce in typename requires(BOOST_IDENTITY_TYPE(( boost::is_same<boost::noncopyable, boost::mpl::_> ))) Copyable, default boost::python::detail::not_specified // Note: Non-type template parameters are not supported by named parameters. ) requires( boost::DefaultConstructible<ClassType> ) // Concepts. class (class_) extends( BOOST_IDENTITY_TYPE(( boost::python::class_<ClassType, Bases, HeldType, Copyable>)) ) ) { CONTRACT_CLASS_INVARIANT_TPL( void ) // Contracts. typedef boost::python::class_<ClassType, Bases, HeldType, Copyable> boost_python_class; public: CONTRACT_CONSTRUCTOR_TPL( public (class_) ( in (char const*) name ) precondition( is_identifier(name) ) initialize( boost_python_class(CONTRACT_CONSTRUCTOR_ARG(name)) ) ) {} }; } // namespace py struct bx { virtual ~bx ( void ) {} }; struct x : bx {}; struct by { virtual ~by ( void ) {} }; struct y : by { }; // Python module, in a Python shell from this directory run: // >>> import pyclass # This will check contracts (preconditions, etc). // >>> help("pyclass"), xx = pyclass.x(), yy = pyclass.x() BOOST_PYTHON_MODULE(pyclass) { // Named parameters. py::class_<py::_ClassType<bx>, py::_Copyable<boost::noncopyable> >("bx"); py::class_<x, py::_HeldType<boost::shared_ptr<x> >, py::_Bases<boost::python::bases<bx> > >("x"); // Deduced parameters. py::class_<by, boost::noncopyable>("by"); py::class_<y, boost::shared_ptr<y>, boost::python::bases<by> >( py::_name = "y"); } Comments welcome. --Lorenzo

on Sun Dec 11 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
On Wed, Nov 9, 2011 at 6:16 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
The goal here is to use Boost.Contract to /completely/ specify the interface for the positive abstract data type.
For whomever is curious, the Boost.Contract named and deduced parameter examples now compile: https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont...
Here's an example that uses a bit of everything: Contracts, concepts, named/deduced function and template parameters:
(gulp) wow! That's _very_ impressive. It's just too bad the syntax is so intrusive on that of C++; it's like a whole new language to learn, debug, etc. There are a few contract programming frameworks out there that are much less capable but at the same time don't intrude so much (e.g. http://www.codeproject.com/KB/cpp/DesignByContract.aspx which probably only builds on MSVC). I wonder if it's possible to make parts of this framework usable in the same way, so that people can approach it more gradually. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Dave Abrahams wrote
on Sun Dec 11 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
On Wed, Nov 9, 2011 at 6:16 AM, Lorenzo Caminiti <lorcaminiti@> wrote:
The goal here is to use Boost.Contract to /completely/ specify the interface for the positive abstract data type.
For whomever is curious, the Boost.Contract named and deduced parameter examples now compile: https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont...
Here's an example that uses a bit of everything: Contracts, concepts, named/deduced function and template parameters:
(gulp) wow! That's _very_ impressive.
It's just too bad the syntax is so intrusive on that of C++; it's like a whole new language to learn, debug, etc. There are a few contract
I wanted to see if and how Contract Programming could be implemented within C++. That came to the (big) cost of: 1) The macro syntax (plus the cryptic pp/compiler errors it generates if you miss something, these errors could be improved a bit but the issue is systematic- the pp is just not capable of detecting syntax errors...). 2) Increased compilation time (x 30 !!!) (but if you disable contract compilation you get ~ x 5 plus it /might/ be possible to improve the implementation to reduce compilation time...). Anyway, now we know just how much C++ macros can be abused ;)
programming frameworks out there that are much less capable but at the same time don't intrude so much (e.g. http://www.codeproject.com/KB/cpp/DesignByContract.aspx which probably only builds on MSVC).
I looked at that before (in fact, I think I studied /all/ Contract Programming work for C++ that was ever done, including A++!!). As far I remember, that approach has a few major issues: No subcontracting and the contracts are in the definitions (instead of declarations).
I wonder if it's possible to make parts of this framework usable in the same way, so that people can approach it more gradually.
If anything, it'd be nice to have a front-end (external to C++) that translates a syntax like the one of N1962 into my library macros. My library syntax follows closely the one of N1962 (pp a part) so this shouldn't be too bad to implement... Thanks. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p429310... Sent from the Boost - Dev mailing list archive at Nabble.com.

It is very impressive. I wonder if a library could be built for writing DSLs using the preprocessor. Much like Boost.Proto lets you write DSLs using C++ operators, another library could be used to build grammars and define transformations based on preprocessor tokens. ----- Original Message ----- From: Dave Abrahams <dave@boostpro.com> To: boost@lists.boost.org Cc: Sent: Thursday, January 12, 2012 8:33 PM Subject: Re: [boost] [contract] syntax redesign on Sun Dec 11 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
On Wed, Nov 9, 2011 at 6:16 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
The goal here is to use Boost.Contract to /completely/ specify the interface for the positive abstract data type.
For whomever is curious, the Boost.Contract named and deduced parameter examples now compile: https://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html/cont...
Here's an example that uses a bit of everything: Contracts, concepts, named/deduced function and template parameters:
(gulp) wow! That's _very_ impressive. It's just too bad the syntax is so intrusive on that of C++; it's like a whole new language to learn, debug, etc. There are a few contract programming frameworks out there that are much less capable but at the same time don't intrude so much (e.g. http://www.codeproject.com/KB/cpp/DesignByContract.aspx which probably only builds on MSVC). I wonder if it's possible to make parts of this framework usable in the same way, so that people can approach it more gradually. -- Dave Abrahams BoostPro Computing http://www.boostpro.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Sat, Jan 14, 2012 at 9:58 PM, paul Fultz <pfultz2@yahoo.com> wrote:
It is very impressive. I wonder if a library could be built for writing DSLs using the preprocessor. Much like Boost.Proto lets you write DSLs using C++ operators, another library could be used to build grammars and define transformations based on preprocessor tokens.
Indeed, my library uses the pp to defined a DSEL for function declarations with contracts, concepts, named parameters, and some C++11 declaration extensions (override, final, etc). Some generalization of the tools used by my library should be possible maybe along the lines of Proto (but I have not looked at implementing such generalization). For now the library implementation performs the following /distinct/ steps: 1) Parse the class and function declarations into their traits (preprocessor-meta-traits) using the pp (pp metaprogramming). 2) Expand the macros based on the parsed function pp-meta-traits generating code for contract, concept, named parameter, etc using the both the pp and the compiler (pp and template metaprogramming, plus C++ programming). These steps are distinct so you can replace step 2 to generate some feature other than contracts, concepts, or named parameters. But step 1) always parses the syntax of the DSEL for declarations with contracts, concepts, and named parameters. So step 1) should be broken down into subtools (maybe like a Preprocessor/Proto)... For example, imagine you want to program a DSEL where a virtual function shall never be public: #define VFUNC_(f) ... // expand to RESULT_TYPE(f) NAME(f) ( PARAMS(f) ) ... #define VFUNC_(f) \ /* if !EMPTY(virtual) && ACCESS == public then error */ \ BOOST_PP_IIF(BOOST_PP_AND( BOOST_COMPL(BOOST_PP_IS_EMPTY(CONTRACT_PP_FUNC_TRAITS_VIRTUAL(f))), CONTRACT_PP_KEYWORD_IS_PUBLIC_FRONT(CONTRACT_PP_FUNC_TRAITS_ACCESS(f))), static_assert(false, "virtual functions cannot be public"); BOOST_PP_TUPLE_EAT(1) \ , \ VFUNC_DECL_ \ )(f) #define VFUNC(sign) \ VFUNC_(CONTRACT_PP_FUNC_TRAITS(sign)) struct x { VFUNC( public int (id) ( int x ) ) { return x; } // ok VFUNC( virtual public int (add) ( int x, int y ) ) { return x + y; } // error- expand to the static assert }; Note that the function pp-meta-traits "f" parsed by step 1) contain /all/ traits of a function declaration because they are parsed using pp metaprogramming so they are not limited by the compiler (which unfortunately does not allow us to detect virtual, public, and other function traits). This is what allows me for example to program "if a function is public then check the class invariants; otherwise do not check class invariants for protected and private functions" (this is a Contract Programming requirement that, without language support, it is perhaps impossible to program unless you use the pp the way I do it here). --Lorenzo

----- Original Message -----
From: Lorenzo Caminiti <lorcaminiti@gmail.com> To: boost@lists.boost.org Cc: Sent: Sunday, January 15, 2012 4:48 AM Subject: Re: [boost] [contract] syntax redesign
It is very impressive. I wonder if a library could be built for writing DSLs using the preprocessor. Much like Boost.Proto lets you write DSLs using C++ operators, another library could be used to build grammars and define
On Sat, Jan 14, 2012 at 9:58 PM, paul Fultz <pfultz2@yahoo.com> wrote: transformations based on preprocessor tokens.
Indeed, my library uses the pp to defined a DSEL for function declarations with contracts, concepts, named parameters, and some C++11 declaration extensions (override, final, etc). Some generalization of the tools used by my library should be possible maybe along the lines of Proto (but I have not looked at implementing such generalization).
For now the library implementation performs the following /distinct/ steps: 1) Parse the class and function declarations into their traits (preprocessor-meta-traits) using the pp (pp metaprogramming). 2) Expand the macros based on the parsed function pp-meta-traits generating code for contract, concept, named parameter, etc using the both the pp and the compiler (pp and template metaprogramming, plus C++ programming).
These steps are distinct so you can replace step 2 to generate some feature other than contracts, concepts, or named parameters. But step 1) always parses the syntax of the DSEL for declarations with contracts, concepts, and named parameters. So step 1) should be broken down into subtools (maybe like a Preprocessor/Proto)...
I'm thinking of library that let's you define a grammar for the parsing stage, which later on can be used to generate the pp-meta-traits. Perhaps, a grammar to parse a function could be defined as this: //type = [const][volatile] var #define TYPE_PARSER(x) \ PP_PARSER_OPT(const) PP_PARSER_OPT(volatile) PP_PARSER_VAR //function = (public | private | protected) [virtual] type var (tuple) #define FUNCTION_PARSER(x) \ PP_PARSER_ALT(public, private, protected) PP_PARSER_OPT(virtual) \ PP_PARSER(TYPE_PARSER) PP_PARSER_VAR (PP_PARSER_TUPLE) And then PP_PARSER_VAR could represent a keyword or something with parenthesis around it(var = keyword | (...)). The parser macro would then transform the grammar into some form of pp data structures. I wonder how much of an EBNF grammar could be implemented, or what the syntax would look like exactly. Furthermore, instead of building a parser, one could just build some transformations, and transform their own DSL into C++ code instead going through some intermediate pp data structures. Ultimately, the parsers would be considered transformations also(much like grammars are considered transformers in Boost.Proto, I believe) Also, on what branch can I find the pp keyword facility? I didn't see it on the trunk.

paul Fultz wrote
----- Original Message -----
From: Lorenzo Caminiti <lorcaminiti@> To: boost@.boost Cc: Sent: Sunday, January 15, 2012 4:48 AM Subject: Re: [boost] [contract] syntax redesign
It is very impressive. I wonder if a library could be built for writing DSLs using the preprocessor. Much like Boost.Proto lets you write DSLs using C++ operators, another library could be used to build grammars and define
On Sat, Jan 14, 2012 at 9:58 PM, paul Fultz <pfultz2@> wrote: transformations based on preprocessor tokens.
Indeed, my library uses the pp to defined a DSEL for function declarations with contracts, concepts, named parameters, and some C++11 declaration extensions (override, final, etc). Some generalization of the tools used by my library should be possible maybe along the lines of Proto (but I have not looked at implementing such generalization).
For now the library implementation performs the following /distinct/ steps: 1) Parse the class and function declarations into their traits (preprocessor-meta-traits) using the pp (pp metaprogramming). 2) Expand the macros based on the parsed function pp-meta-traits generating code for contract, concept, named parameter, etc using the both the pp and the compiler (pp and template metaprogramming, plus C++ programming).
These steps are distinct so you can replace step 2 to generate some feature other than contracts, concepts, or named parameters. But step 1) always parses the syntax of the DSEL for declarations with contracts, concepts, and named parameters. So step 1) should be broken down into subtools (maybe like a Preprocessor/Proto)...
I'm thinking of library that let's you define a grammar for the parsing stage, which later on can be used to generate the pp-meta-traits. Perhaps, a grammar to parse a function could be defined as this:
//type = [const][volatile] var #define TYPE_PARSER(x) \ PP_PARSER_OPT(const) PP_PARSER_OPT(volatile) PP_PARSER_VAR
//function = (public | private | protected) [virtual] type var (tuple) #define FUNCTION_PARSER(x) \ PP_PARSER_ALT(public, private, protected) PP_PARSER_OPT(virtual) \ PP_PARSER(TYPE_PARSER) PP_PARSER_VAR (PP_PARSER_TUPLE)
And then PP_PARSER_VAR could represent a keyword or something with parenthesis around it(var = keyword | (...)). The parser macro would then transform the grammar into some form of pp data structures. I wonder how much of an EBNF grammar could be implemented, or what the syntax would look like exactly. Furthermore, instead of building a parser, one could just build some transformations, and transform their own DSL into C++ code instead going through some intermediate pp data structures. Ultimately, the parsers would be considered transformations also(much like grammars are considered transformers in Boost.Proto, I believe)
Yes, it makes sense. Right now step 1) does something _somewhat_ similar but it would need to be redesigned to be exposed the macros as a public API (as you suggest and possibly along the lines of Proto): #define CONTRACT_DETAIL_PP_FUNC_TRAITS_ACCESS_TRAIT_(sign) \ CONTRACT_DETAIL_PP_TRAITS_AUX_NIL /* optional trait */ \ CONTRACT_DETAIL_PP_TRAITS_AUX_KEYWORD3(sign, \ BOOST_DETAIL_PP_KEYWORD_IS_PUBLIC_FRONT, public, \ BOOST_DETAIL_PP_KEYWORD_IS_PROTECTED_FRONT, protected, \ BOOST_DETAIL_PP_KEYWORD_IS_PRIVATE_FRONT, private) http://contractpp.svn.sourceforge.net/viewvc/contractpp/branches/syn/src/contract/detail/preprocessor/traits/func/access.hpp?revision=1047&view=markup #define CONTRACT_DETAIL_PP_FUNC_TRAITS_VIRTUAL_TRAIT_(sign) \ CONTRACT_DETAIL_PP_TRAITS_AUX_NIL /* optional trait */ \ CONTRACT_DETAIL_PP_TRAITS_AUX_KEYWORD(sign, \ BOOST_DETAIL_PP_KEYWORD_IS_VIRTUAL_FRONT, virtual) http://contractpp.svn.sourceforge.net/viewvc/contractpp/branches/syn/src/contract/detail/preprocessor/traits/func/virtual.hpp?revision=1047&view=markup And all the bits are put together here: http://contractpp.svn.sourceforge.net/viewvc/contractpp/branches/syn/src/contract/detail/preprocessor/traits/func.hpp?revision=1047&view=markup
Also, on what branch can I find the pp keyword facility? I didn't see it on the trunk.
It's moving :) Currently, it's in Boost.Local under boost/detail/preprocessor/keyword/: https://svn.boost.org/svn/boost/sandbox/local/boost/detail/preprocessor/keyw... But during Local review it was decided to only put in Local the 3-4 pp-keywords that Local needs (const, void, inline, bind, etc) so finally I'll move the pp-keywords back into Boost.Contract (under src/contract/detail/preprocessor/keyword/). Thanks. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p429885... Sent from the Boost - Dev mailing list archive at Nabble.com.

on Sun Dec 11 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
Comments welcome.
also, at http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont...: s/comma/colon/ everywhere. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

on Sun Dec 11 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
Comments welcome.
Here's another: where are the header files!? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Dave Abrahams wrote
on Sun Dec 11 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
Comments welcome.
Here's another: where are the header files!?
The library is actually hosted on SF (and not yet in Boost sandbox): http://contractpp.svn.sourceforge.net/viewvc/contractpp/branches/syn/ It's still a work in progress and the docs are completely out of date... Next I have to write the docs and release a new version on SF. Then _maybe_ a Boost review... Thanks. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p429306... Sent from the Boost - Dev mailing list archive at Nabble.com.

on Fri Jan 13 2012, lcaminiti <lorcaminiti-AT-gmail.com> wrote:
Dave Abrahams wrote
on Sun Dec 11 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
Comments welcome.
Here's another: where are the header files!?
The library is actually hosted on SF (and not yet in Boost sandbox):
http://contractpp.svn.sourceforge.net/viewvc/contractpp/branches/syn/
Ah, I didn't think to look in the branches.
It's still a work in progress and the docs are completely out of date... Next I have to write the docs and release a new version on SF. Then _maybe_ a Boost review...
Thank /you/. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Fri, Sep 2, 2011 at 3:14 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Fri Sep 02 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
For whomever is curious, I have implemented the new Boost.Contract syntax. Here's large number of examples that now compile with the new syntax: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont...
Wow. This is a powerful new language! How does this relate to the work Matt Calabrese started on implementing concepts in C++11 (see the
/Perhaps/ this could be done (but I'm not positive...): http://contractpp.svn.sourceforge.net/viewvc/contractpp/trunk/doc/html/contr... --Lorenzo

lcaminiti wrote:
After a long time of inactivity for Boost.Contract, I am considering how to re-design its macro syntax to make it simpler.
Hello all, Playing with pp a bit more I realized this alternative syntax is also possible: CONTRACT_CLASS( // option A template( typename T ) class (vector) ) { CONTRACT_CLASS_INVARIANT( assert(empty() == (size() == 0)) // no trailing `,` or `;` etc assert(size() <= capacity) ) public: CONTRACT_FUNCTION_TPL( public void (push_back) ( (const T&) value ) precondition( assert(size() < max_size()) ) postcondition( var(auto old_size = CONTRACT_OLDOF size()) var(auto old_capacity = CONTRACT_OLDOF capacity()) assert(back() == val) requires(boost::has_equal_to<T>::value) assert(size() == old_size + 1) assert(capacity() >= old_capacity) const_assert(x, y, x == y) static_assert(sizeof(T) >= sizeof(int), "large enough") ) ) ; }; While currently I am implementing: CONTRACT_CLASS( // option B template( typename T ) class (vector) ) { CONTRACT_CLASS_INVARIANT( empty() == (size() == 0), size() <= capacity ) public: CONTRACT_FUNCTION_TPL( public void (push_back) ( (const T&) value ) precondition( size() < max_size() ) postcondition( auto old_size = CONTRACT_OLDOF size(), auto old_capacity = CONTRACT_OLDOF capacity(), back() == val, requires boost::has_equal_to<T>::value, size() == old_size + 1, capacity() >= old_capacity, const( x, y ) x == y, static_assert(sizeof(T) >= sizeof(int), "large enough") ) ) ; }; I think option B (current) is still better than option A because A requires (1) more parenthesis and (2) the extra assertion word spelled out all the times but A doesn't require the trailing `,` which is a plus. Do you have a strong opinion about which one is better between A and B? I'd say B is better but I'm quite biased at this point ;) Thanks a lot. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p384791... Sent from the Boost - Dev mailing list archive at Nabble.com.

on Tue Sep 27 2011, lcaminiti <lorcaminiti-AT-gmail.com> wrote:
Do you have a strong opinion about which one is better between A and B? I'd say B is better but I'm quite biased at this point ;)
+1, it's B all the way. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (5)
-
Dave Abrahams
-
lcaminiti
-
Lorenzo Caminiti
-
Matt Calabrese
-
paul Fultz