我正在写一些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 ++标准进行解释。
答案 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
并产生您真正想要的序列。