I wrote an enum iterator a while ago for these cases
enum Foo {
A, B, C, Last
};
typedef litb::enum_iterator<Foo, A, Last> FooIterator;
int main() {
FooIterator b(A), e;
std::cout << std::distance(b, e) << " values:" << std::endl;
std::copy(b, e, std::ostream_iterator<Foo>(std::cout, "\n"));
while(b != e) doIt(*b++);
}
If you are interested, here is the code. If you like, you can extend it to be a random access iterator by providing +
, <
, []
and friends. Algorithms like std::distance
will thank you by providing O(1)
time complexity for the then random-access iterator.
#include <cassert>
namespace litb {
template<typename Enum, Enum Begin, Enum End>
struct enum_iterator
: std::iterator<std::bidirectional_iterator_tag, Enum> {
enum_iterator():c(End) { }
enum_iterator(Enum c):c(c) { }
enum_iterator &operator=(Enum c) {
this->assign(c);
return *this;
}
enum_iterator &operator++() {
this->inc();
return *this;
}
enum_iterator operator++(int) {
enum_iterator cpy(*this);
this->inc();
return cpy;
}
enum_iterator &operator--() {
this->dec();
return *this;
}
enum_iterator operator--(int) {
enum_iterator cpy(*this);
this->dec();
return cpy;
}
Enum operator*() const {
assert(c != End && "not dereferencable!");
return c;
}
bool equals(enum_iterator other) const {
return other.c == c;
}
private:
void assign(Enum c) {
assert(c >= Begin && c <= End);
this->c = c;
}
void inc() {
assert(c != End && "incrementing past end");
c = static_cast<Enum>(c + 1);
}
void dec() {
assert(c != Begin && "decrementing beyond begin");
c = static_cast<Enum>(c - 1);
}
private:
Enum c;
};
template<typename Enum, Enum Begin, Enum End>
bool operator==(enum_iterator<Enum, Begin, End> e1, enum_iterator<Enum, Begin, End> e2) {
return e1.equals(e2);
}
template<typename Enum, Enum Begin, Enum End>
bool operator!=(enum_iterator<Enum, Begin, End> e1, enum_iterator<Enum, Begin, End> e2) {
return !(e1 == e2);
}
} // litb