C/C++:任何获得反思枚举的方法?

Tho*_*ini 17 c c++ reflection enums

我遇到过这种情况很多次......

 enum Fruit {
  Apple,
  Banana,
  Pear,
  Tomato
 };
Run Code Online (Sandbox Code Playgroud)

现在我有了Fruit f; // banana,我想要从f字符串开始"Banana"; 或者我已经string s = "Banana"和我想去了Banana // enum value or int.

到目前为止,我一直这样做..假设枚举在Fruit.h中:

// Fruit.cpp
const char *Fruits[] = {
 "Apple",
 "Banana",
 "Pear",
 "Tomato",
 NULL
};
Run Code Online (Sandbox Code Playgroud)

显然这是一个混乱的解决方案.如果开发人员在标题中添加了新的水果,并且没有在Fruits []中添加新条目(不能责怪他,他们必须在两个不同的文件中!)应用程序会蓬勃发展.

有没有一种简单的方法可以做我想要的,一切都在一个文件中?预处理器黑客,外星魔法,任何东西......

PS:这与"为了一切"的反思相反,在编译器中实现起来真的很微不足道.看到问题有多常见(至少对我而言)我真的不敢相信没有reflective enum Fruit..甚至在C++ 0x中都没有.

PS2:我正在使用C++,但我也将这个问题标记为C,因为C有同样的问题.如果您的解决方案仅包含C++,那对我来说没问题.

Gon*_*alo 32

这个需要在外部文件中定义水果.这将是fruit.cpp的内容:

#define FRUIT(name) name
enum Fruit {
#include "fruit-defs.h"
NUM_FRUITS
};
#undef FRUIT
#define FRUIT(name) #name
const char *Fruits [] = {
#include "fruit-defs.h"
NULL
};
#undef FRUIT
Run Code Online (Sandbox Code Playgroud)

这将是水果定义:

FRUIT(Banana),
FRUIT(Apple),
FRUIT(Pear),
FRUIT(Tomato),
Run Code Online (Sandbox Code Playgroud)

只要值从0开始并且是连续的,它就可以工作......

更新:如果您需要非连续值,请使用C99将此解决方案与Richard Pennington的解决方案混合使用.即,类似于:

// This would be in fruit-defs.h
FRUIT(Banana, 7)
...
// This one for the enum
#define FRUIT(name, number) name = number
....
// This one for the char *[]
#define FRUIT(name, number) [number] = #name
Run Code Online (Sandbox Code Playgroud)

  • 它们标记枚举 (NUM_FRUITS) 或数组 (NULL) 的结尾。NUM_FRUITS 的值将比最后一个水果的值多 1。它们都可以用来迭代数组的元素直到结束。 (2认同)

Ric*_*ton 9

我发现的c99方式有助于减少错误:

enum Fruit {
  APPLE,
  BANANA
};
const char* Fruits[] = {
 [APPLE] = "APPLE",
 [BANANA] = "BANANA"
};
Run Code Online (Sandbox Code Playgroud)

您可以添加枚举,即使是在中间,也不要破坏旧定义.当然,您仍然可以为忘记的值获取NULL字符串.