是否可以定义将以以下方式扩展的预处理器宏。

MACRO1(x) (y,z,w)
--> MACRO2(x,y,z,w)
MACRO1的扩展能否以某种方式消耗宏调用后的列表的左括号,并用MACRO2(x,替换它,以便预处理器将结果作为有效的宏调用接受(假设已定义MACRO2)并且不会引发unterminated argument list错误?

我试图做这样的事情
#define STRANGE_MACRO(...) __VA_ARGS__
#define STRIP_PAREN(...) __VA_ARGS__)
#define PREPEND_AND_APPLY_STRANGE(x) STRANGE_MACRO(x,STRIP_PAREN

像这样调用它:
PREPEND_AND_APPLY_STRANGE(x) (y,z,w)

产生unerminated argument list错误。有办法使它起作用吗?

至于我想要这种行为的原因,这是出于美学的考虑,我认为最好像这样进行宏调用
MACRO1(identifier) (
    more
    complex
    arguments
)


MACRO2(identifier,
    more
    complex
    arguments
)

我希望将前者转变为后者。如果在预处理程序规则内不可能,没什么大不了,我将接受它,但如果可以,我想知道窍门。

最佳答案

如果要在替换列表中包含不匹配的左括号,则需要添加一个间接层:

#define LPAREN (

#define PREPEND_AND_APPLY_STRANGE(x) STRANGE_MACRO LPAREN x,STRIP_PAREN

这样,在正确的语法完成之前,不会将括号视为调用的一部分。

不幸的是,这种技术有一个局限性:到STRANGE_MACRO的调用完全构建时,它已经可以重新扫描了,因为表达式的开始和结束是在两次不同的调用之间构建的,在同一级别上,整个过程永远不会出现在一个重新扫描列表中-并且永远不会真正扩展。您只会在输出中转储STRANGE_MACRO ( x,y,z,w)。您需要在顶层强制重新扫描:
#define EXPAND(...) __VA_ARGS__

该宏不执行任何操作,但确实意味着它的参数将作为一个完整的单元放入重新扫描列表中,并最终扩展。因此,最接近所需语法的是:
EXPAND(

MACRO1(identifier) (
    ....
)
MACRO1(identifier) (
    ....
)

)

...因此您不需要使用自己的EXPAND来毁损每个自定义块,但是您确实需要将整个程序包装为一个。不,您不能通过在#include中放置EXPAND指令来隐藏包装器,因为指令不能出现在调用中。 (不过,也许您可​​以通过重新发明namespace或可能需要语法的类似东西来使它有用。)

这也有一个缺点,即C编译器将整个程序视为一行,这会在一定程度上损害错误报告-尽管您已经半途而废,因为每个声明块也似乎只在一行上原始版本有效。

关于c++ - 将参数前置到列表,然后在C预处理程序宏中应用另一个宏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23385337/

10-10 18:32