
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