
Here is my latest range.hpp file, I should probably change the name back to constrained_value because of the conflict with iterator ranges? I am a first time boost contributor , so I would appreciate comments on my style, and whether this file overextends its intended scope. To Jeff Garland: do you want me to be fully compatible with your existing constrained_value type, so that you can link this in without rewriting a thing? Thanks to all in advance. /* range.hpp Boost range type mini-library based on the constrained_value type by Jeff Garland, http://www.crystalclearsoftware.com/ modified and enhanced by Christopher Diggins http://www.cdiggins.com license available at http://www.boost.org/LICENSE_1_0.txt */ #ifndef BOOST_RANGE_HPP #define BOOST_RANGE_HPP // TEMP: my preference is to disallow silent casts to range // the default will have to decided upon by consensus #define BOOST_RANGE_SILENT_CASTS 1 // you can explicitly turn off range_checking #ifdef BOOST_RANGE_CHECKING_OFF #define BOOST_RANGE_CHECKING_ON 0 #else #define BOOST_RANGE_CHECKING_ON 1 #endif #include <limits> namespace boost { namespace range { using namespace std; namespace policies { // some common policies for range types static inline double less_than(double d) { return (1.0 - numeric_limits<double>::epsilon()) * d; } template<typename T> struct root { typedef T value; static void on_error(T value, T min, T max) { cerr << "range violation: " << value << " outside of range " << min << " to " << max << endl; } }; struct unsigned_double : root<double> { static const value min() { return 0.0; }; }; struct zero_to_one_inclusive : public unsigned_double { static const value max() { return 1.0; }; }; struct zero_to_one_exclusive : public unsigned_double { static const value max() { return less_than(1.0); }; }; struct percent : public unsigned_double { static const value max() { return 100.0; }; }; struct degrees : public unsigned_double { static const value max() { return less_than(360.0); }; }; const double PI = 3.1415926535897; struct radians : public unsigned_double { static const value max() { return less_than(2 * PI); }; }; template <typename T, T min_T, T max_T> struct simple : root<T> { static const value min() { return min_T; }; static const value max() { return max_T; }; }; template<int base> struct whole_number : simple<unsigned short int, 0, base - 1> { }; }; // a simple range class template<class policy> class range { public: typedef range<policy> self; typedef typename policy::value value; range() : m(min()) { } range(const self& x) { m = x.get_value(); } #ifdef BOOST_RANGE_SILENT_CASTS range(value x) { assign(x); } #endif static const value min() { return policy::min(); } static const value max() { return policy::max(); } const value get_value() const { return m; } operator value() { return m; } self& operator=(const self& x) { m = x; return *this; } #ifdef BOOST_RANGE_SILENT_CASTS self& operator=(value x) { assign(x); return *this; } #endif void assign(const value& x) { #ifdef BOOST_RANGE_CHECKING_ON { if (x+1 < min()+1) { policy::on_error(x, min(), max()); return; } if (x > max()) { policy::on_error(x, min(), max()); return; } } #endif m = x; } private: value m; }; // some common types expressed as ranges typedef range<policies::zero_to_one_inclusive> probability; typedef range<policies::zero_to_one_exclusive> distribution; typedef range<policies::percent> percent; typedef range<policies::degrees> degrees; typedef range<policies::radians> radians; typedef range<policies::whole_number<24> > hour; typedef range<policies::whole_number<60> > minute; typedef range<policies::whole_number<60> > second; typedef range<policies::whole_number<10> > decimal_digit; typedef range<policies::whole_number<16> > hex_digit; typedef range<policies::whole_number<8> > octal_digit; typedef range<policies::whole_number<7> > day_of_week; typedef range<policies::whole_number<12> > greg_month; typedef range<policies::whole_number<365> > greg_day_of_year; }; }; #endif // BOOST_RANGE_HPP Christopher Diggins http://www.cdiggins.com http://www.heron-language.com