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. ]