__VA_ARGS__在BOOST_PP_SEQ_FOR_EACH

时间:2018-04-04 23:59:10

标签: c++ variadic-macros boost-preprocessor

我的实际代码示例非常复杂,但我将尝试通过简单的说明总结我所看到的行为。

我有一个宏,我希望能够单独调用,或者多次作为更大宏扩展的一部分调用:

#define DO_STUFF(name,...)   \
    STUFF1(name,__VA_ARGS__) \
    STUFF2(name,__VA_ARGS__) \
    STUFF3(name,__VA_ARGS__)

我可以直接在源文件中使用DO_STUFF(dave, int, char)和类似的变体,它会生成我期望的代码。

我还想用另一个输入列表调用DO_STUFF宏的大列表。为了处理这种情况,我使用带有一系列元组(或可变序列)的boost预处理器:

DO_LOTS_OF_STUFF(
      (dave, ball, pen)          \
      (alice, cat, dog, bicycle) \
      (peter, bird) )

我对DO_LOTS_OF_STUFF的定义如下:

#define DO_LOTS_OF_STUFF(SEQ)       \
   BOOST_PP_SEQ_FOR_EACH(              \
     INVOKE_DS, _,                     \
     BOOST_PP_VARIADIC_SEQ_TO_SEQ(SEQ) \
   )

#define INVOKE_DS( r, data, elem )      \
   DO_STUFF(BOOST_PP_TUPLE_ENUM(elem)); \

如上所示,当我调用DO_LOTS_OF_STUFF时,STUFF1STUFF2STUFF3都会在末尾用额外的逗号调用,并带有空参数。

如果我在调用DO_STUFF的位置(通过更改其名称)中断扩展,则预处理器输出看起来像我期望的那样:

DO_STUFF(dave, ball, pen)
DO_STUFF(alice, cat, dog, bicycle)
DO_STUFF(peter, bird)

如果我在STUFF1STUFF2STUFF3级别中断展开,它们会在输出中显示一个额外的空参数:

STUFF1(dave, ball, pen,)
STUFF2(dave, ball, pen,)
STUFF3(dave, ball, pen,)
STUFF1(alice, cat, dog, bicycle,)
STUFF2(alice, cat, dog, bicycle,)
STUFF3(alice, cat, dog, bicycle,)
STUFF1(peter, bird,)
STUFF2(peter, bird,)
STUFF3(peter, bird,)

这只是预处理器元编程中要避免的事情之一,例如“不要使用##”吗? “不要在嵌套宏中使用__VA_ARGS__”?

有关如何定义DO_STUFFDO_LOTS_OF_STUFF以避免此问题的任何建议吗?

1 个答案:

答案 0 :(得分:0)

我弄清楚发生了什么。

我使用DO_STUFF调用SEQ_FOR_EACH的地方我使用BOOST_PP_TUPLE_ENUM

#define INVOKE_DS( r, data, elem )      \
   DO_STUFF(BOOST_PP_TUPLE_ENUM(elem)); \

BOOST_PP_TUPLE_ENUM将元组(a,b,c,d)转换为逗号分隔的标记,而不使用括号a,b,c,d

我认为这意味着DO_STUFF(BOOST_PP_TUPLE_ENUM((a,b,c,d)))会看到4个参数,但事实上它仍然只能看到a,b,c,d。{/ p>

此扩展:

#define DO_STUFF(name,...)   \
    STUFF1(name,__VA_ARGS__) \
    STUFF2(name,__VA_ARGS__) \
    STUFF3(name,__VA_ARGS__)

实际上是在这种情况下添加额外的空参数,因为__VA_ARGS__为空。

所以解决方案非常简单。我刚刚创建了DO_STUFF案例

中使用的DO_LOTS_OF_STUFF宏的不同变体
#define DO_LOTS_OF_STUFF(SEQ)       \
   BOOST_PP_SEQ_FOR_EACH(              \
     INVOKE_DS, _,                     \
     BOOST_PP_VARIADIC_SEQ_TO_SEQ(SEQ) \
   )

#define INVOKE_DS( r, data, elem )      \
   DO_STUFF_1(BOOST_PP_TUPLE_ENUM(elem)); \

#define DO_STUFF_1(tuple_args)   \
    STUFF1(tuple_args) \
    STUFF2(tuple_args) \
    STUFF3(tuple_args)
相关问题