Re: [boost] [contract] syntax redesign

This use case is different then the above (more compelling). The issues here is that when programming contracts you quickly start using extra checks (and especially ==) which add additional requirements on generic types. For example, in this case T does not have to be EqualityComparable to program the body but you still want to program and check the postcondition when T happens to be EqualityComparable. I have been thinking to solve this issue by providing:
namespace contract {
temlate< typename T> bool equal(T const& left, T const& right) ... }
equal will return true if T is not EqualityComparable and left == right if T is EqualityComparable. That way you can program the contracts using contract::equal(x, y) without introducing additional requirements on T at all but still checking the contract conditions for EqualityComparable types. I will also expand equal to handle containers (compare all elements of a vector, etc) and I will provide similar functions for other operations. All of these contract helper functions will be in a separate header <contract/utility.hpp>. I have not started to implement this yet.
To me, this problem with equality indicates that Boost.Concept already proves useful, as it explores practical aspects of implementing DbC in C++ and its interactions with other C++ features.
BTW, I am also wondering if it would be useful to implement a fully contracted version of the STL probably in contract::std:
#include <contract/std/vector.hpp> #include <contract/std/algorithm.hpp>
contract::std::vector<int> v; contract::std::for_each(v.begin(), v.end(), ...);
I think Boost.Contract can essentially implement most/all of the interface contracts (preconditions, postconditions, invariants, and concepts) documented by the SGI: http://www.sgi.com/tech/stl/<http://www.google.com/url?sa=D&q=http://www.sgi.com/tech/stl/&usg=AFQjCNHIn0O8JZNSqHs0gRzjbMfuTDBeFw> Would such a contract::std be any useful?
This is a fair question. And probably best answered by the authors of contract programming proposal for C++. What ISO C++ Committee did with nearly every new language feature (concepts, auto, noexcept, constexpr, initializer_list) was to also use it in library in order to (i) prove that the future is usable, (ii) give a solid example of how the feature should be used. So, along this reasoning, there are good reasons to do it. I can see, however, also valid reasons against it: Boost only recently approved STL containers library rewrite: Boost.Containers ( http://svn.boost.org/svn/boost/sandbox/move/libs/container/doc/html/index.ht...). It already has Boost.PointerContainer (although it serves a different purpose it may be distracting that they are defined and described separately). so now, each time I use a container I will have to decide if I am using std::vector or boost::container::vector. Now if I need to consider a third option boost::contract::stl::vector it really gets hard. And would they all interoperable with one another? Perhaps if the contracts were implemented in Boost.Container, but then... I expect that Boost.Contract syntax may discourage some Boost users, that just want to use (and perhaps debug) Container library. Overwhelming them with the new syntax might discourage them from using Boost.Container. If you implement your containers separately, it is likely that they will just not be used. Difficult to say... Regards, &rzej

Andrzej Krzemienski wrote:
This use case is different then the above (more compelling). The issues here is that when programming contracts you quickly start using extra checks (and especially ==) which add additional requirements on generic types. For example, in this case T does not have to be EqualityComparable to program the body but you still want to program and check the postcondition when T happens to be EqualityComparable. I have been thinking to solve this issue by providing:
namespace contract {
temlate< typename T> bool equal(T const& left, T const& right) ... }
equal will return true if T is not EqualityComparable and left == right if T is EqualityComparable. That way you can program the contracts using contract::equal(x, y) without introducing additional requirements on T at all but still checking the contract conditions for EqualityComparable types. I will also expand equal to handle containers (compare all elements of a vector, etc) and I will provide similar functions for other operations. All of these contract helper functions will be in a separate header <contract/utility.hpp>. I have not started to implement this yet.
To me, this problem with equality indicates that Boost.Concept already proves useful, as it explores practical aspects of implementing DbC in C++ and its interactions with other C++ features.
I am thinking to address the issue of "how to write contracts using == (or similar operations) for generic types that might not be EqualityComparable without adding the EqualityComparable type requirement when it is not necessary for implementing the body" as follow: I can provide a contract::trivial::operator== which trivially returns true. Programmers can add a using directive in their contracts (e.g., postconditions) if they wish to use such a trivial operator. The trivial operator will be used by C++ only if no other operator if found for the type so only if the type was not EqualityComparable. For example: #include <contract.hpp> #include <contract/trivial.hpp> // the trivial contract helpers #include <boost/concept_check.hpp> template< typename T > class Addable { // User-defined concept. T x; T y; void return_type ( T ); // Used to check addition returns type `T`. public: BOOST_CONCEPT_USAGE(Addable) { return_type(x + y); // Check addition `T operator+(T x, T y)`. } }; CONTRACT_FUNCTION( template( typename T ) requires( Addable<T> ) (T) (add) ( (T) x, (T) y ) postcondition( using contract::trivial::operator==, // (1) auto result = return, result == x + y // Trivial == if T not EqualityComparable. ) ) { return x + y; } Note that using directives (and namespace aliases) such as (1) above are allowed within contracts because they cannot change the run-time state so they maintain the contract constant-correctness requirement. Furthermore, contracts are specified with the function declarations so usually in header files where namespace manipulations are best avoided and therefore it might be handy to manipulate names locally within the contracts to simply names. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p379443... Sent from the Boost - Dev mailing list archive at Nabble.com.
participants (2)
-
Andrzej Krzemienski
-
lcaminiti