我正在写一些Boost。预处理器元程序,我有以下问题。考虑以下宏(这是对问题的简化说明):
#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++的任何标准解释
我认为如果遇到ITERATION(ARGS)
,则取ITERATION_IMPL(hello, args(), world)
,用ARGS
替换args
,然后重新扫描。ITERATION_IMPL(hello, ARGS(), world)
是ITERATION_IMPL
的调用。因此,它取((p1),(p2),(p3),(p4))
,并用ARGS()
(以及其他参数)替换p2
。然后重新扫描并解析为((hello),(a, b),(world),())
。我不知道为什么它的工作原理,它调用一个4参数宏与3个参数在你的情况下。
你可以做
#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)
将执行您所期望的操作。
EDIT: test with 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)))
当外部EVAL
的X
被ITERATION_IMPL EVAL((hello, args(), world))
取代时,它会重新扫描并产生ITERATION_IMPL (hello, a, b, world)
来调用EVAL
。然后,它再次重新扫描ITERATION
的调用,并生成您真正想要的序列。