自动为枚举添加类似Java-enum的功能

时间:2014-01-06 08:25:21

标签: java c++ c enums

在Java中,枚举具有C / C ++枚举中缺少的几个功能。我希望能够定义枚举,例如,某些宏ENUM(Color, Red, Green, Blue)ENUM(Color, {Red, Green, Blue} )或什么不是,并且已经定义了以某种方式实现这些功能的枚举。

具体来说,我希望能够做到以下几点:

for (Color p : Color::values()) { }

Color color(Red);
cout << "My face shone a bright " << color;

Color color = valueOf<Color>("Green");
/* ... */
cout  << "It ain't easy being " << color;

备注:

  • 如果解决方案允许我为每个枚举值指定(整数)值(例如,红色为2,绿色为5,蓝色为19),则为奖励积分。
  • 如果解决方案允许我指定'继承类型',则为奖励积分,a-la enum Color : unsigned char { Red, Green, Blue};
  • 欢迎使用Boost的建议,但我更愿意只使用标准库。
  • 我与宏没有'结婚'。
  • 这个问题与this one有关,但不一样。这个问题主要涉及允许多个数据字段,而我并不关心这一点,并对适当的单一类型枚举感到满意。

2 个答案:

答案 0 :(得分:1)

经过一些实验后,我得到了以下内容。

#define empty
#define secondSyn()         second
#define second(x, y, ...)   y
#define endOfParams()       ,
#define mapSyn()            mapc empty
#define mapc(fun, x, ...)   , secondSyn empty () (x(), fun(x) mapSyn empty () (fun, __VA_ARGS__))
#define map(fun, x, ...)    secondSyn empty () (x(), fun(x) mapSyn empty () (fun, __VA_ARGS__))


#define eval(...)           eval2(eval2(eval2(eval2(eval2(eval2(eval2(eval2(__VA_ARGS__))))))))
#define eval2(...)          eval3(eval3(eval3(eval3(eval3(eval3(eval3(eval3(__VA_ARGS__))))))))
#define eval3(...)          eval4(eval4(eval4(eval4(eval4(eval4(eval4(eval4(__VA_ARGS__))))))))
#define eval4(...)          eval5(eval5(eval5(eval5(eval5(eval5(eval5(eval5(__VA_ARGS__))))))))
#define eval5(...)          __VA_ARGS__


#define IDENTITY(x)         x
#define STRINGIFY(x)        #x

#define DEFENUM(name, ...) \
    enum name { eval(map(IDENTITY, __VA_ARGS__, endOfParams)) }; \
    char *name##Names[] = { eval(map(STRINGIFY, __VA_ARGS__, endOfParams)) }

DEFENUM(Color, Red, Green, Blue);

它与我的gcc一起工作。您应该在实际使用之前重命名大多数宏。对于非常大的枚举,您需要添加eval6宏。希望它有所帮助。

答案 1 :(得分:0)

这篇文章是一个很好的分析。 http://www.wambold.com/Martin/writings/typesafe-enums.html

它的价值在于使用一些c ++习语和方法而不是简单的天真转换。

这是“最终”版本(添加toString等):

class Suit
{
public:
  enum private_SUIT_ { CLUBS, DIAMONDS, HEARTS, SPADES };

private:
  typedef private_SUIT_ SUIT_;
  SUIT_ S_;

  template <SUIT_ S> class Literal;

public:
  template <SUIT_ S>
  Suit (const Literal<S>&) : S_ (S) {}

  SUIT_ toEnum () const { return S_; }

  inline friend bool operator== (Suit s, Suit t) { return s.S_ == t.S_; }
  inline friend bool operator!= (Suit s, Suit t) { return ! (s == t); }

  static const Literal<CLUBS>    clubs;
  static const Literal<DIAMONDS> diamonds;
  static const Literal<HEARTS>   hearts;
  static const Literal<SPADES>   spades;
};

template <Suit::private_SUIT_ S>
class Suit::Literal : private Suit
{
public:
  Suit::private_SUIT_ toEnum () const { return S; }
private:
  friend class Suit;
  Literal () : Suit (*this) {}
  // Prevent treating literals as objects
  void* operator new (size_t);      // outlawed
  void  operator delete (void*);    // outlawed
  void  operator= (const Literal&); // outlawed
  void* operator& () const;         // outlawed
};