这适用于 C 预处理专家:
如何在enum
中声明一些标识符列表,稍后在switch-statement检查中是否列出了标识符?
我需要的例子:
typedef enum { e1, e2, e3, e4, e5, e6 } e;
e x;
switch (x) {
#if DECLARED_IN_ENUM (e1)
case e1 : ...
#endif
/* etc. */
}
我想过使用Boost序列并将其扩展为枚举中的逗号分隔列表,但是如果序列包含某个令牌,我该如何检查呢?
编辑:我能用Boost做的是:
#define e1 e1
#define e2 e2
#define e3 e3
#define e4 e4
#define e5 e5
#define e6 e6
#define E (e1)(e2)(e3)(e4)(e5)(e6)
typedef enum { BOOST_PP_SEQ_ENUM(E) } e;
e x;
switch (x) {
#if defined (e1)
case e1 : ...
#endif
/* etc. */
}
那不是很漂亮,我更喜欢这样的东西:
#define E (e1)(e2)(e3)(e4)(e5)(e6)
typedef enum { BOOST_PP_SEQ_ENUM(E) } e;
e x;
switch (x) {
#if BOOST_PP_SEQ_CONTAINS (e1,E)
case e1 : ...
#endif
/* etc. */
}
但是如何实施BOOST_PP_SEQ_CONTAINS
?
答案 0 :(得分:4)
你做不到。 C预处理器不“理解”C编程语言,它只是标记它。它不知道“枚举”究竟意味着什么。编译器处理。
如果你想在预处理器中测试一些东西,那么你必须提供预处理器宏供它使用。
编辑:抱歉,错过了您打算使用Boost.Preprocessor。我不知道是否可以提供必要的宏,一旦你在enum的定义中包含了Boost的内容。
答案 1 :(得分:2)
我认为BOOST_PP_SEQ_CONTAINS
无法实施。这将要求您能够比较两个预处理令牌序列,这是您无法做到的。
但是,如果你稍微重新排列逻辑,你可以得到更接近你想要的东西。首先,我们需要一些辅助宏来与BOOST_PP_SEQ_FOR_EACH
一起使用:
#include <boost/preprocessor.hpp>
// General purpose macros:
#define EXPAND_ENUM_CASE_2(text1, text2) text1 ## text2
#define EXPAND_ENUM_CASE(r, data, elem) \
case elem : EXPAND_ENUM_CASE_2(data ## _ ## CASE ## _ , elem)
我们可以像原始问题一样定义枚举器列表和枚举:
#define WORKDAY_ENUMERATORS (Monday)(Tuesday)(Wednesday)(Thursday)
enum Workday { BOOST_PP_SEQ_ENUM(WORKDAY_ENUMERATORS) };
正如你所看到的,我已经离开星期五,因为周五没有人真正工作。让我们考虑一个函数,它返回一些描述星期几的文本。
我们不是测试枚举器是否包含在列表中,而是使用宏定义每个值的个案:
#define WORKDAY_CASE_Monday { return "Mondays suck"; }
#define WORKDAY_CASE_Tuesday { return "Tuesdays are better than Mondays"; }
#define WORKDAY_CASE_Wednesday { return "Hooray for humpday!"; }
#define WORKDAY_CASE_Thursday { return "Thursdays are okay"; }
#define WORKDAY_CASE_Friday { return "No one really works on Friday"; }
然后,我们使用WORKDAY_ENUMERATORS
生成列表的正确case语句,并将枚举数与WORKDAY_CASE_
前缀连接起来:
const char* get_day_text(Workday d)
{
switch (d)
{
BOOST_PP_SEQ_FOR_EACH(EXPAND_ENUM_CASE, WORKDAY, WORKDAY_ENUMERATORS)
}
return "WTF?! That's not a workday!";
}
如果WORKDAY_ENUMERATORS
列表中未包含某一天,则不会为其生成任何案例。
因为我们在使用预处理器时应该礼貌,然后我们取消定义我们使用的宏:
#undef WORKDAY_CASE_Monday
#undef WORKDAY_CASE_Tuesday
#undef WORKDAY_CASE_Wednesday
#undef WORKDAY_CASE_Thursday
#undef WORKDAY_CASE_Friday
我认为这有点难看,但这是获得几乎所有搜索结果的一种方法。
答案 2 :(得分:0)
请勿使用enum
。它没有任何用处。使用#define
声明所有常量,并使用#ifdef
。
答案 3 :(得分:0)
一种方法是拥有一个很棒的大#define或“.h”文件,它涵盖你所有的工作日(.h文件的优点是你不需要用反斜杠结束所有喜欢)并且包括所有相关的宏中的信息。然后#define生成器宏做某事,调用大宏(或#include头),#undef生成器宏并定义它做其他事情,再调用大宏等等。在这种情况下,一个变体生成器宏将生成类似“case ENUM_foo:func_foo(); break;”的内容。然后,您可以为适当的func_ *函数编写所有适当的代码,并在适当时调用它们。