在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;
备注:
enum Color : unsigned char { Red, Green, Blue};
答案 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
};