Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C预处理器宏:检查是否声明了令牌_C++_Boost_C Preprocessor_Boost Preprocessor - Fatal编程技术网

C++ C预处理器宏:检查是否声明了令牌

C++ C预处理器宏:检查是否声明了令牌,c++,boost,c-preprocessor,boost-preprocessor,C++,Boost,C Preprocessor,Boost Preprocessor,这是为C预处理器专家准备的: 如何使用一些标识符的列表声明enum,然后在switch语句中检查列表中是否包含标识符 我需要的示例: typedef enum { e1, e2, e3, e4, e5, e6 } e; e x; switch (x) { #if DECLARED_IN_ENUM (e1) case e1 : ... #endif /* etc. */ } 我曾想过使用一个Boost序列,并将其扩展为枚举中的逗号分隔列表,但我以后如何检查该序列是否包含某个标记 编辑:

这是为C预处理器专家准备的:

如何使用一些标识符的列表声明
enum
,然后在switch语句中检查列表中是否包含标识符

我需要的示例:

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\u PP\u SEQ\u CONTAINS
。C预处理器并不“理解”C编程语言,它只是将其标记化。它不知道“枚举”的实际含义。编译器处理这个问题

如果要在预处理器中测试某些内容,则必须提供预处理器宏供其使用


编辑:抱歉,您没有注意到您打算使用Boost.Preprocessor。我不知道,一旦您在枚举的定义中加入了Boost的内容,它是否能够提供必要的宏。

只是不要使用
enum
。它没有任何用处。使用
#define
声明所有常量,并使用
#ifdef

我认为
BOOST\u PP\u SEQ\u CONTAINS
无法实现。这将要求您能够比较两个预处理令牌序列,而这是您无法做到的

然而,如果你重新安排你的逻辑一点,你可以得到一些更接近你想要的东西。首先,我们需要两个helper宏用于每个的
BOOST\u PP\u SEQ\u:

#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_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_枚举数
并将枚举数与
WORKDAY_case_
前缀连接,为列表生成正确的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\u枚举器
列表中,则不会为其生成任何案例

因为我们在使用预处理器时应该有礼貌,所以我们会取消定义我们使用的宏:

#undef WORKDAY_CASE_Monday
#undef WORKDAY_CASE_Tuesday
#undef WORKDAY_CASE_Wednesday
#undef WORKDAY_CASE_Thursday
#undef WORKDAY_CASE_Friday

我认为这有点难看,但这是一种获得您想要的结果的方法。

一种方法是使用一个很大的#define或“.h”文件,它覆盖您的所有工作日(该.h文件的优点是您不需要以反斜杠结束所有喜欢),并在宏中包含它们的所有相关信息。然后#定义生成器宏以执行某些操作,调用大宏(或#包含标题),#取消定义生成器宏并定义它以执行其他操作,再次调用大宏,等等。在这种情况下,生成器宏的一个变体将生成类似“case ENUM_foo:func_foo();break;”的内容。然后你可以为适当的函数函数写出所有合适的代码,它们会被适当地调用。

我删除了C标记,因为你也标记了Boost。Boost预处理器宏应该独立于C++扩展,所以它们可以在C中使用,太好了。你也知道如何获得Boost输出,为每种情况都创建一行新行吗?@Thomas:不知道,但我不知道这有什么关系:在对预处理指令进行评估后,新行并不重要。当gcc打印出错误时,这可能会对我有所帮助(如“之前的预期标识符”()之类的错误)行长为20000个字符时可能很难识别)即使在普通C语言中,
enum
也比
#define
有一个很大的优势:调试器知道用
enum
定义的常量,但用
#define
定义的常量通常不知道。不太重要但仍然有用的是,如果忘记包含一些o,编译器有足够的信息可以对您大喊大叫f在<代码>开关语句中的值<代码> EnUM <代码>。在C++中,您也得到了实际上属于它们自己类型的常数的好处。我将给出这样的结果,但它仍然是一个实现问题。如果编译器和调试器实现足够聪明,它们可以知道<代码>定义< <代码> >就像<代码> EnUM#define
严格来说比
enum
更强大。你可以用
#define
做一些有用的事情,但用
enum
做不到,但什么都没有(在实际语言的范围内,而不是调试器或特定于实现的东西)你可以用<代码> EnUM <代码>完成,你不能用<代码>定义< <代码>。我用C++编码,把我的枚举放在类或命名空间中,这是不可能的。好,你有一个很好的理由使用<代码> EnUM < /C>。我希望每个人都停止标记C++问题,把C假装为同一种语言……使用
enum
常量可以做的一件事是使用
#define
不能做的一件事-使用具有相同名称的结构或联合标记和/或成员。可以发布一个简短的代码示例吗?这听起来像James的建议。
#undef WORKDAY_CASE_Monday
#undef WORKDAY_CASE_Tuesday
#undef WORKDAY_CASE_Wednesday
#undef WORKDAY_CASE_Thursday
#undef WORKDAY_CASE_Friday