The Artima Developer Community
Sponsored Link

Weblogs Forum
Policy Based Range Checking Class for C++

1 reply on 1 page. Most recent reply: Aug 27, 2005 4:04 AM by cyril romain

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 1 reply on 1 page
Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Policy Based Range Checking Class for C++ (View in Weblogs)
Posted: Jun 21, 2005 8:02 AM
Reply to this message Reply
Summary
I have recently updated my constrained_value class which among other things allows one to easily define range checking integers.
Advertisement
I wanted to share my overhauled constrained_value policy driven class with the community. A constrained_value value type allows you to take an arbitrary value type and define how assignment occurs through a policy parameter. One common usage is to do range checking, but it is much more flexible than this.

The class itself is as follows:

  template<class Policy_T>
  struct constrained_value
  {
    public:
      // public typedefs
      typedef typename Policy_T policy_type;
      typedef typename Policy_T::value_type value_type;
      typedef constrained_value self;

      // default constructor
      constrained_value() : m(Policy_T::default_value) { }
      constrained_value(const self& x) : m(x.m) {  }
      explicit constrained_value(const value_type& x) { Policy_T::assign(m, x); }
      operator value_type() const { return m; }

      void assign(const value_type& x) {
        Policy_T::assign(m, x);
      }

      // assignment operations
      self& operator=(const value_type& x) { assign(x); return *this; }
      self& operator+=(const value_type& x) { assign(m + x); return *this; }
      self& operator-=(const value_type& x) { assign(m - x); return *this; }
      self& operator*=(const value_type& x) { assign(m * x); return *this; }
      self& operator/=(const value_type& x) { assign(m / x); return *this; }
      self& operator%=(const value_type& x) { assign(m % x); return *this; }
      self& operator>>=(int x) { assign(m >> x); return *this; }
      self& operator<<=(int x) { assign(m << x); return *this; }

      // unary operations
      self operator-() { return self(-m); }
      self operator+() { return self(-m); }
      self operator!() { return self(!m); }
      self operator~() { return self(~m); }

      // binary operations
      friend self operator+(const self& x, const value_type& y) { return self(x) += y; }
      friend self operator-(const self& x, const value_type& y) { return self(x) -= y; }
      friend self operator*(const self& x, const value_type& y) { return self(x) *= y; }
      friend self operator/(const self& x, const value_type& y) { return self(x) /= y; }
      friend self operator%(const self& x, const value_type& y) { return self(x) %= y; }
      friend self operator>>(const self& x, int y) { return self(x) >>= y; }
      friend self operator<<(const self& x, int y) { return self(x) <<= y; }

      // comparison operators
      friend bool operator<(const self& x, const self& y) { return x.m < y.m; }
      friend bool operator>(const self& x, const self& y) { return x.m > y.m; }
      friend bool operator<=(const self& x, const self& y) { return x.m <= y.m; }
      friend bool operator>=(const self& x, const self& y) { return x.m >= y.m; }
      friend bool operator==(const self& x, const self& y) { return x.m == y.m; }
      friend bool operator!=(const self& x, const self& y) { return x.m != y.m; }
    private:
      value_type m;
  };

If you want to use this to define a range checking integer, you need to supply a policy such as this one:

  template<int Min_N, int Max_N>
  struct range_throwing_int_policy
  {
    typedef int value_type;
    const static value_type default_value = Min_N;
    static void assign(value_type& lvalue, const value_type& rvalue) {
      STATIC_ASSERT(Min_N < Max_N);
      if ((rvalue < Min_N) || (rvalue > Max_N)) {
        throw std::range_error("out of valid range");
      }
      lvalue = rvalue;
    }
  };

  typedef constrained_value<range_throwing_int_policy<0, 6> > weekday;
  typedef constrained_value<range_throwing_int_policy<0, 23> > hour;
  typedef constrained_value<range_throwing_int_policy<0, 60> > minute;
  typedef constrained_value<range_throwing_int_policy<0, 60> > second;
  typedef constrained_value<range_throwing_int_policy<0, 31> > day;
  typedef constrained_value<range_throwing_int_policy<0, 11> > month;

More creative policies are also possible, such as assuring that the number is always even or odd:

  struct even_numbers_policy
  {
    typedef int value_type;
    const static value_type default_value = 0;
    static void assign(value_type& lvalue, const value_type& rvalue) {
      if (rvalue % 2 != 0) {
        // rounds towards zero
        if (rvalue > 0) lvalue = rvalue - 1;
        else lvalue = rvalue + 1;
      }
      else {
        lvalue = rvalue;
      }
    }
  };

  struct odd_numbers_policy
  {
    typedef int value_type;
    const static value_type default_value = 1;
    static void assign(value_type& lvalue, const value_type& rvalue) {
      if (rvalue % 2 == 0) {
        // round towards zero policy
        if (rvalue > 0) lvalue = rvalue - 1;
        else lvalue = rvalue + 1;
      }
      else {
        lvalue = rvalue;
      }
    }
  };

  typedef constrained_value<even_numbers_policy> even_number;
  typedef constrained_value<odd_numbers_policy> odd_number;

I welcome your comments and improvements.


cyril romain

Posts: 3
Nickname: cromain
Registered: Aug, 2005

Re: Policy Based Range Checking Class for C++ Posted: Aug 27, 2005 4:04 AM
Reply to this message Reply
How do you use such policy to manage float or double value ?
Tell me if I'm wrong but template does not allow to write things like :
template<float Min_N, float Max_N>
struct range_throwing_float_policy

Best regards, and be an Heron man !

Flat View: This topic has 1 reply on 1 page
Topic: My Pycon 2005 Presentation Previous Topic   Next Topic Topic: Python-Ruby Comparison

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use