如何将宏扩展的结果分成不同的参数?

时间:2011-04-15 11:57:24

标签: c++ c visual-studio-2008 boost-preprocessor

我正在写一些Boost.Preprocessor元程序,我有以下问题。考虑以下宏(这是一个简化来说明问题):

#define ITERATION_IMPL(p1, p2, p3, p4) ((p1),(p2),(p3),(p4))
#define ITERATION(args) ITERATION_IMPL(hello, args(), world)

#define ARGS() a, b
ITERATION(ARGS)

预处理的输出是:

((hello),(a, b),(world),())

这表明args()未分成多个参数。根据我对标准的理解,宏的参数在被粘贴到替换列表之前完全展开。因此,我期望以下扩展序列:

ITERATION(ARGS)
ITERATION_IMPL(hello, ARGS(), world)
ITERATION_IMPL(hello, a, b, world)
((hello),(a),(b),(world))

这是我想要的结果。如何在不修改ITERATION_IMPL和调用本身的情况下实现它?

编辑:如果不可能(我猜它是),请根据任何C或C ++标准进行解释。

1 个答案:

答案 0 :(得分:3)

我认为如果遇到ITERATION(ARGS),则需要ITERATION_IMPL(hello, args(), world),将args替换为ARGS,然后重新扫描。 ITERATION_IMPL(hello, ARGS(), world)是对ITERATION_IMPL的调用。因此,它需要((p1),(p2),(p3),(p4)),并将p2替换为ARGS()(以及其他参数)。然后重新扫描并解析为((hello),(a, b),(world),())。我不知道为什么它在你的情况下调用一个带有3个参数的4参数宏。

你可以做到

#define EVAL(X) X
#define ITERATION(args) ITERATION_IMPL EVAL((hello, args(), world))

这需要X,替换(hello, ARGS(), world),然后重新扫描,导致ARGS()a, b替换。生成的令牌字符串ITERATION_IMPL (hello, a, b, world)然后会按预期执行。

编辑:用GCC测试:)

编辑:我注意到你想要字符串((hello),(a),(b),(world)),但我的答案产生字符串ITERATION_IMPL (hello, a, b, world)。我认为这是因为在调用ITERATION后重新扫描时,它会将IERATION_IMPL EVAL((hello, ARGS(), world))替换为ITERATION_IMPL (hello, a, b, wold)。然后需要另一次扫描才能注意到它现在可以使用这些参数调用ITERATION_IMPL。所以ITERATION应该是

#define ITERATION(args) EVAL(ITERATION_IMPL EVAL((hello, args(), world)))

如果外部X的{​​{1}}被EVAL替换,则会重新扫描并为ITERATION_IMPL EVAL((hello, args(), world))的调用生成ITERATION_IMPL (hello, a, b, world)。然后它再次重新扫描以调用EVAL并产生您真正想要的序列。