Để thêm vào @StackedCrooked câu trả lời, bạn có thể quá tải operator++
, operator--
và operator*
và có iterator như chức năng.
enum Color {
Color_Begin,
Color_Red = Color_Begin,
Color_Orange,
Color_Yellow,
Color_Green,
Color_Blue,
Color_Indigo,
Color_Violet,
Color_End
};
namespace std {
template<>
struct iterator_traits<Color> {
typedef Color value_type;
typedef int difference_type;
typedef Color *pointer;
typedef Color &reference;
typedef std::bidirectional_iterator_tag
iterator_category;
};
}
Color &operator++(Color &c) {
assert(c != Color_End);
c = static_cast<Color>(c + 1);
return c;
}
Color operator++(Color &c, int) {
assert(c != Color_End);
++c;
return static_cast<Color>(c - 1);
}
Color &operator--(Color &c) {
assert(c != Color_Begin);
return c = static_cast<Color>(c - 1);
}
Color operator--(Color &c, int) {
assert(c != Color_Begin);
--c;
return static_cast<Color>(c + 1);
}
Color operator*(Color c) {
assert(c != Color_End);
return c;
}
Hãy thử nghiệm với một số <algorithm>
mẫu
void print(Color c) {
std::cout << c << std::endl;
}
int main() {
std::for_each(Color_Begin, Color_End, &print);
}
Bây giờ, Color
là một iterator hai chiều liên tục. Đây là một lớp tôi có thể tái sử dụng được mã hóa trong khi thực hiện thủ công ở trên. Tôi nhận thấy nó có thể làm việc cho nhiều enums hơn, do đó, lặp lại cùng một mã một lần nữa là khá tẻ nhạt
// Code for testing enum_iterator
// --------------------------------
namespace color_test {
enum Color {
Color_Begin,
Color_Red = Color_Begin,
Color_Orange,
Color_Yellow,
Color_Green,
Color_Blue,
Color_Indigo,
Color_Violet,
Color_End
};
Color begin(enum_identity<Color>) {
return Color_Begin;
}
Color end(enum_identity<Color>) {
return Color_End;
}
}
void print(color_test::Color c) {
std::cout << c << std::endl;
}
int main() {
enum_iterator<color_test::Color> b = color_test::Color_Begin, e;
while(b != e)
print(*b++);
}
Thực hiện sau.
template<typename T>
struct enum_identity {
typedef T type;
};
namespace details {
void begin();
void end();
}
template<typename Enum>
struct enum_iterator
: std::iterator<std::bidirectional_iterator_tag,
Enum> {
enum_iterator():c(end()) { }
enum_iterator(Enum c):c(c) {
assert(c >= begin() && c <= end());
}
enum_iterator &operator=(Enum c) {
assert(c >= begin() && c <= end());
this->c = c;
return *this;
}
static Enum begin() {
using details::begin; // re-enable ADL
return begin(enum_identity<Enum>());
}
static Enum end() {
using details::end; // re-enable ADL
return end(enum_identity<Enum>());
}
enum_iterator &operator++() {
assert(c != end() && "incrementing past end?");
c = static_cast<Enum>(c + 1);
return *this;
}
enum_iterator operator++(int) {
assert(c != end() && "incrementing past end?");
enum_iterator cpy(*this);
++*this;
return cpy;
}
enum_iterator &operator--() {
assert(c != begin() && "decrementing beyond begin?");
c = static_cast<Enum>(c - 1);
return *this;
}
enum_iterator operator--(int) {
assert(c != begin() && "decrementing beyond begin?");
enum_iterator cpy(*this);
--*this;
return cpy;
}
Enum operator*() {
assert(c != end() && "cannot dereference end iterator");
return c;
}
Enum get_enum() const {
return c;
}
private:
Enum c;
};
template<typename Enum>
bool operator==(enum_iterator<Enum> e1, enum_iterator<Enum> e2) {
return e1.get_enum() == e2.get_enum();
}
template<typename Enum>
bool operator!=(enum_iterator<Enum> e1, enum_iterator<Enum> e2) {
return !(e1 == e2);
}
Làm cách nào để bạn chọn chức năng cho cuộc gọi? Bạn có thể đăng một số mã giả làm thế nào để bạn giả sử để làm điều đó? Nó có thể giúp chúng tôi giúp bạn. –
được cập nhật cho krill – jameszhao00
Để xem thời gian chạy tại http://stackoverflow.com/questions/1292426/is-there-any-well-known-paradigm-for-iterating-through-enum. (Nếu không có thời gian biên dịch, câu hỏi của bạn sẽ là bản sao chính xác của nó.) – sbi