枚举在C ++中的枚举 [英] Enumerate over an enum in C++

查看:160
本文介绍了枚举在C ++中的枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中,是否可以枚举一个枚举(运行时或编译时(首选)),并调用函数/生成每个迭代的代码?



示例用例:

 枚举abc 
{
开始
a,
b,
c,
end
}
每个(__enum__member__在abc)
{
function_call(__ enum__member__);
}






合理的重复: p>


解决方案

要添加到 @StackedCrooked 回答,你可以重载 operator ++ operator - operator * 并具有类似功能的迭代器。

 枚举颜色{
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;
};
}

颜色&运算符++(颜色& c){
assert(c!= Color_End);
c = static_cast< Color>(c + 1);
return c;
}

颜色运算符++(Color& c,int){
assert(c!= Color_End);
++ c;
return static_cast< Color>(c - 1);
}

颜色&运算符 - (Color& c){
assert(c!= Color_Begin);
return c = static_cast< Color>(c - 1);
}

颜色运算符 - (Color& c,int){
assert(c!= Color_Begin);
--c;
return static_cast< Color>(c + 1);
}

颜色运算符*(颜色c){
assert(c!= Color_End);
return c;
}

让我们用一些< algorithm> 模板

  void print(Color c){
std :: cout< c <的std :: ENDL;
}

int main(){
std :: for_each(Color_Begin,Color_End,& print);
}

现在,颜色是一个恒定的双向迭代器。这是一个可重用的类,我在上面手动进行编码。我注意到它可以工作更多的枚举,所以重复相同的代码一遍又一遍是相当乏味的

  //测试代码enum_iterator 
// --------------------------------

命名空间color_test {
枚举颜色{
Color_Begin,
Color_Red = Color_Begin,
Color_Orange,
Color_Yellow,
Color_Green,
Color_Blue,
Color_Indigo ,
Color_Violet,
Color_End
};

颜色begin(enum_identity< Color>){
return Color_Begin;
}

颜色结束(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 ++);
}

执行如下。

 模板< typename T> 
struct enum_identity {
typedef T type;
};

命名空间详细信息{
void begin();
void end();
}

模板< typename枚举>
struct enum_iterator
:std :: iterator< std :: bidirectional_iterator_tag,
枚举> {
enum_iterator():c(end()){}

enum_iterator(枚举c):c(c){
assert(c> = begin() ;& c< = end());
}

enum_iterator& operator =(Enum c){
assert(c> = begin()&& c< = end());
this-> c = c;
return * this;
}

static枚举begin(){
使用细节:: begin; // re-enable ADL
return begin(enum_identity< Enum>());
}

static枚举结束(){
使用细节:: end; //重新启用ADL
return end(enum_identity< Enum>());
}

enum_iterator& operator ++(){
assert(c!= end()&&增量过去结束?
c = static_cast&Enum>(c + 1);
return * this;
}

enum_iterator操作符++(int){
assert(c!= end()&&增量过去结束?
enum_iterator cpy(* this);
++ * this;
return cpy;
}

enum_iterator& operator - (){
assert(c!= begin()& amp;&减量超出开始?
c = static_cast<枚举>(c - 1);
return * this;
}

enum_iterator运算符 - (int){
assert(c!= begin()&&减量超出开始?
enum_iterator cpy(* this);
- * this;
return cpy;
}

枚举算子*(){
assert(c!= end()&&不能取消引用结束迭代器);
return c;
}

枚举get_enum()const {
return c;
}

private:
枚举c;
};

template< typename枚举>
bool operator ==(enum_iterator< Enum> e1,enum_iterator&Enum> e2){
return e1.get_enum()== e2.get_enum();
}

模板< typename枚举>
bool operator!=(enum_iterator&Enum> e1,enum_iterator&Enum> e2){
return!(e1 == e2);
}


In C++, Is it possible to enumerate over an enum (either runtime or compile time (preferred)) and call functions/generate code for each iteration?

Sample use case:

enum abc
{    
    start
    a,
    b,
    c,
    end
}    
for each (__enum__member__ in abc)
{    
    function_call(__enum__member__);    
}


Plausible duplicates:

解决方案

To add to @StackedCrooked answer, you can overload operator++, operator-- and operator* and have iterator like functionality.

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;
}

Let's test with some <algorithm> template

void print(Color c) {
  std::cout << c << std::endl;
}

int main() {
  std::for_each(Color_Begin, Color_End, &print);
}

Now, Color is a constant bidirectional iterator. Here is a reusable class i coded while doing it manually above. I noticed it could work for many more enums, so repeating the same code all over again is quite tedious

// 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++);
}

Implementation follows.

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);
}

这篇关于枚举在C ++中的枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆