2013-03-14 48 views
2

名称下面迭代器宏给我(不能改变)捕获使用C宏

#define ITERATE(MACRO) \ 
    MACRO(v1) \ 
    MACRO(v2) \ 
    MACRO(v3) \ 
    MACRO(v4) 

这背后的想法是,我现在可以定义自己的一个参数的宏,并将其传递到迭代器扩大为v1v2,v3,v4。例如:

#define MYSTUFF(X) doSth(X); 
ITERATE(MYSTUFF) 

将扩大到

doSth(v1); doSth(v2); doSth(v3); doSth(v4); 

我现在的问题是,我想这想传递一个额外的参数为MYSTUFF超出一个提供的另一个宏内调用ITERATEITERATE

为了实现这个目标,我希望我可以用下面的结构捕捉额外的参数名称:

#define PARTIAL(T) FULL(UUU,T) 
#define FULL(U,V) doSth(U,V) 
#define START(UUU) ITERATE(PARTIAL) 
START(bla) 

我希望,当ITERATE(PARTIAL)被扩展为:

FULL(UUU,v1) FULL(UUU,v2) FULL(UUU,v3) FULL(UUU,v4) 

我居然还会捕获START的参数UUU,它将被替换为bla。不幸的是,情况并非如此(至少在gcc中)。

  • 你知道这样的名称捕获是否可以实现不同吗?
  • 或者您可能有不同的想法如何解决将额外参数传入MACRO的问题?
  • 我可能会被允许更改ITERATOR定义本身,但前提是它不破坏任何现有代码已经使用它。
+1

如果您不允许更改宏,您是否至少允许用非宏代码替换它? – stefan 2013-03-14 16:43:03

+0

当然,我可以简单*不*使用'ITERATE',或者自己创建一个可以接受更多参数的函数 - 如果这是您要求的。但我宁愿避免这种情况。 – CygnusX1 2013-03-14 16:48:24

+4

我建议彻底摆脱宏的使用,而不是写另一个 – stefan 2013-03-14 16:50:55

回答

2

你不能这样做。宏你的START()基本上只有一个参数,然后丢弃。

你可以做的是定义UUU你需要它,例如。

#define PARTIAL(T) FULL(UUU,T) 
#define FULL(U,V) doSth(U,V) 
#define START() ITERATE(PARTIAL) 

// ... 

#define UUU blah 

START() 

#undef UUU 
2

你的问题,简化的,看起来是这样的:

#define FOO UUU 
#define START(UUU) FOO 
START(5) 

这里发生了什么:

  • 宏观START在线路遇到START(5)
    • START是一个函数样宏,所以它变得扩大与论点UUU = 5):
      • 阶段1(自变量扩展):宏参数是宏扩展
        没有任何反应,5不是宏。
        身体:FOO
      • 阶段2(argument prescan):宏参数代入宏体。
        没有任何反应,UUU不在体内。
        身体:FOO
      • 阶段3(膨胀):身体宏扩展再次
        FOO被扩展成UUU,这不是一个宏。
        身体:UUU

我想不出任何聪明的方式来扩大FOO身体内部的说法预扫描发生之前。我认为不可能直接做你想做的事。

跟@Hasturkun的解决方法,并使UUU宏,而不是一个参数。

+0

感谢您对宏如何工作的明确解释。 – CygnusX1 2013-03-14 17:38:49