// Copyright 2006 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt ) #ifndef __SPEC_HPP_ #define __SPEC_HPP_ #include #include #include namespace spec { // forward declaration template struct spec; template struct are_not_equal_exception : std::exception { are_not_equal_exception(const T & value, const _T & expected) : _value(value) , _expected(expected) { std::ostringstream message(""); message << "spec:: value supplied (" << _value << ") and expected value (" << _expected << ") are not equal."; _message = message.str(); }; const char * what() const throw (){ return _message.c_str(); }; T _value; _T _expected; std::string _message; }; template struct are_equal_exception : std::exception { are_equal_exception(const T & value, const _T & expected) : _value(value) , _expected(expected) { std::ostringstream message(""); message << "spec:: value supplied (" << _value << ") and expected value (" << _expected << ") are equal."; _message = message.str(); }; const char * what() const throw (){ return _message.c_str() ; }; T _value; _T _expected; std::string _message; }; template struct less_than_lower_bound_exception : std::exception { less_than_lower_bound_exception (const T & value, const _T & lower_bound) : _value(value) , _lower_bound(lower_bound) { std::ostringstream message(""); message << "spec:: value supplied (" << _value << ") is less than the lower bound (" << _lower_bound << ")"; _message = message.str(); }; const char * what() const throw (){ return _message.c_str() ; }; T _value; _T _lower_bound; std::string _message; }; template struct more_than_upper_bound_exception : std::exception { more_than_upper_bound_exception(const T & value, const _T & upper_bound) : _value(value) , _upper_bound(upper_bound) { std::ostringstream message(""); message << "spec:: value supplied (" << _value << ") is more than the upper bound (" << _upper_bound << ")"; _message = message.str(); }; const char * what() const throw (){ return _message.c_str() ; }; T _value; _T _upper_bound; std::string _message; }; namespace detail { template struct between_impl; template struct should_impl { explicit should_impl(T & value) : _value(value) { }; template bool equal(const _T & expected) const { if (_value == expected) return true; throw are_not_equal_exception(_value, expected) ; }; template bool not_equal(const _T & expected) const { if (_value != expected) return true; throw are_equal_exception(_value, expected) ; }; template bool be_less_than(const _T & upper_bound) const { if (_value < upper_bound) return true; throw more_than_upper_bound_exception(_value, upper_bound); }; template bool be_more_than(const _T & lower_bound) const { if (_value > lower_bound) return true; throw less_than_lower_bound_exception(_value, lower_bound); }; template between_impl<_T> be_between(const _T & lower_bound) const { if (_value < lower_bound) throw less_than_lower_bound_exception(_value, lower_bound); return between_impl<_T>(_value); }; T & _value; }; template struct between_impl { explicit between_impl(T & value) : _value(value) { }; template bool and(const _T & upper_bound) { if (_value < upper_bound) return true; throw more_than_upper_bound_exception(_value, upper_bound); }; T & _value; }; }; // namespace detail template inline spec value (const T & v) { return spec(v); }; template struct spec { T _value; detail::should_impl should; spec(const T & v) : _value(v), should(_value){ }; }; }; // namespace spec #endif // __SPEC_HPP_