j'ai écrit un iterator ENUM il y a un moment pour ces cas
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++);
}
Si vous êtes intéressé, est le code ici. Si vous le souhaitez, vous pouvez l'étendre pour devenir un itérateur à accès aléatoire en fournissant +
, <
, []
et vos amis. Des algorithmes tels que std::distance
vous remercient en fournissant O(1)
complexité temporelle pour l'itérateur à accès aléatoire de l'époque.
#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
Stop! Tu me rends nostalgique de Pascal. –