Topic: Range types? (was Inheriting Enums)


Author: dick@silicon.csci.csusb.edu (Dr. Richard Botting)
Date: 1995/10/27
Raw View
Steve Clamage (clamage@Eng.Sun.COM) wrote on the old topic):
: For example:

:  class chili {
:  public:
:   enum hotness { low=0, medium=500, high=1000, scary=10000 };
:  };

So, a declaration like
 enum range{first=1, last=20};
permits
 for( range i=first; i<=last; i++)
  whatever;
An hence... (forgive my ignorance below):
 template <int first, int last> class range{
  enum{ FIRST=first, LAST=last }v;
 public:
  range(){v=FIRST;}
  range val(){return v}
  void reset(){v=FIRST;}
  bool ok(){return FIRST<=v && v<=LAST;}
  range& operator++{ v++; return *this;}
 ...
 }

 for(range<0,17> i; ok(i); i++)

 for(range<0,32>chn; ok(chn); chn++)
 { char c=char(chn);
   whatever...
 }

--
 dick@csci.csusb.edu=rbotting@wiley.csusb.edu.
Find out what's new at http://www.csci.csusb.edu/doc/www.sites.html
Disclaimer:`CSUSB may or may not agree with this message`.
Copyright(1995):Copy this freely but include the following link to the
<a href="http://www.csci.csusb.edu/dick/signature.html">author's signature</a>

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Jak Kirman <jak@cs.brown.edu>
Date: 1995/10/29
Raw View
>>>>> "Richard" == Richard Botting <dick@silicon.csci.csusb.edu> writes:
In article <46o780$2au@news.csus.edu> dick@silicon.csci.csusb.edu (Dr. Richard Botting) writes:

 Richard>  template <int first, int last> class range{
 Richard>   enum{ FIRST=first, LAST=last }v;
 Richard>  public:
 Richard>   range(){v=FIRST;}
 Richard>   range val(){return v}
 Richard>   void reset(){v=FIRST;}
 Richard>   bool ok(){return FIRST<=v && v<=LAST;}
 Richard>   range& operator++{ v++; return *this;}
 Richard>  ...
 Richard>  }

 Richard>  for(range<0,17> i; ok(i); i++)

 Richard>  for(range<0,32>chn; ok(chn); chn++)
 Richard>  { char c=char(chn);
 Richard>    whatever...
 Richard>  }

It seems to me that a range is a container, and that you really want to
iterate through the container.  Something like:

  // 0 to 16, for consistency with STL ranges, which are [start,end)
  Range<int> r (0, 17);

  cout << "copying range to stdout with a for loop" << endl;
  for(Range<int>::iterator i = r.begin(); i != r.end(); i++)
    cout << *i << endl;

  cout << "copying range to stdout with STL copy" << endl;
  copy (r.begin(), r.end(), ostream_iterator<int> (cout, "\n"));

  cout << "copying range to stdout backwards with STL copy" << endl;
  copy (r.rbegin(), r.rend(), ostream_iterator<int> (cout, "\n"));

I don't see the advantage of making the bounds part of the template; I
think of Range<T> as being a type that represents any range of objects
of type T.  This allows easy copying of ranges, which seems a useful
feature.

Here are the definitions for the code above.  I have probably missed
some requirements, and maybe the iterators should be random_access; I am
not sure.  Any comments?


// STL headers
#include <iterator.h>
#include <algo.h>

// Standard library headers
#include <iostream.h>

template <class T>
class Range
{
public:
  class Iterator : public bidirectional_iterator<T,ptrdiff_t>
  {
  private:
    T current;
  public:
    Iterator () { }
    Iterator (const T& t) { current = t; }
    Iterator operator++ () { ++current; return *this; }
    Iterator operator++ (int) { Iterator tmp = *this; ++current; return tmp; }
    Iterator operator-- (int) { --current; return *this; }
    Iterator operator-- () { Iterator tmp = *this; --current; return tmp; }
    T operator* () const { return current; }
    friend bool operator== (const Iterator& i1, const Iterator& i2)
    { return *i1 == *i2; }

  };
  typedef T value_type;
  typedef T& reference;
  typedef const T& const_reference;
  typedef T* pointer;
  typedef Iterator iterator;
  typedef Iterator const_iterator;
  typedef reverse_bidirectional_iterator<const_iterator, value_type,
    reference, ptrdiff_t> reverse_iterator;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
private:
  T first;
  T last;
public:
  Range() {} // empty range -- first and last will both be created with
             // default constructor, so begin() and end() should test equal.
  Range(const T& f, const T& l) {first = f; last = l;}
  iterator begin() const { return iterator(first); }
  iterator end() const { return iterator (last); }
  reverse_iterator rbegin() const {return reverse_iterator(iterator(last-1)); }
  reverse_iterator rend() const {return reverse_iterator (iterator(first-1)); }
};

main (int argc, char *argv[])
{
  Range<int> r (0, 17);  // 0 to 16, for consistency with STL [start,end)

  cout << "copying range to stdout with a for loop" << endl;
  for(Range<int>::iterator i = r.begin(); i != r.end(); i++)
    cout << *i << endl;

  cout << "copying range to stdout with STL copy" << endl;
  copy (r.begin(), r.end(), ostream_iterator<int> (cout, "\n"));

  cout << "copying range to stdout backwards with STL copy" << endl;
  copy (r.rbegin(), r.rend(), ostream_iterator<int> (cout, "\n"));

  // not terribly useful, but it works :-)

  char **days = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
                 "Saturday", "Sunday", 0};

  Range<char **> r (days[0], days[7]);
  typedef Range<char **>::iterator Iterator;

  for (Iterator i = r.begin(); i!= r.end(); i++)
    cout << **i << endl;


}

 Jak Kirman     jak@cs.brown.edu        http://www.cs.brown.edu/people/jak/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Every \item command in item_list must have an optional argument.
                                                              -- LaTeX p.168


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]