我认为它会扩展为 getFourth(type, 1, type, 2, type, 3) 所以我们应该选择 2(因为 2 是第 4 个参数)
宏不是这样工作的。宏扩展从外向内发生。此外,有两个扩展机会:(1)在参数替换期间,(2)在发生替换后生成替换列表。仅当宏中的参数对应于替换列表中的一个(并且该参数未使用 # 运算符或参与粘贴 (##))时,才会发生参数替换扩展。
例如,如果我们有:
#define foo(b,c) b c
getFourth(some_type(1),some_type(2),some_type(3),foo(some_type,(4)),x)
那么getFourth现在有5个参数,所以可以调用了。扩展的第一步是参数替换; getFourth 的替换列表是_4,它只提到了一个参数。对应的参数是foo(some_type,(4))。因为_4 没有被粘贴或字符串化,处理器可以评估foo(some_type,(4))。这导致some_type (4),进一步扩展为type, 4。所以现在,type, 4 替换了_4。我们已经完成了参数替换。
我们只剩下type, 4。这里还有一次重新扫描,但在此步骤中没有任何反应。但请注意,some_type(1)、some_type(2) 和 some_type(3) 不仅在getFourth 之前没有得到评估,而且它们根本没有得到评估 ,因为替换列表中没有提到它们。
有人可以建议如何解决它吗?
只要您要扩展的内容是 getFourth 的参数 1 到 3,它们甚至不会计算。但是你可以把它变成一个带括号的列表,然后然后应用宏,使用类似于我上面所做的技巧:
#define CALL(a,b) a b
CALL(getFourth,(some_type(1),some_type(2),some_type(3))).
现在,getFourth 和 (some_type(1),some_type(2),some_type(3)) 只是 CALL 的参数,它提到了这两个参数。因此,在参数替换期间,getFourth 本身会“评估”(因为这不足以调用类对象宏,所以它保持原样),并被放入a。 (some_type(1),some_type(2),some_type(3)) 评估并放入b。该评估变为(type, 1,type, 2,type, 3)。所以你最终得到getFourth (type, 1,type, 2,type, 3)。现在进行重新扫描,在此期间 getFourth 使用您期望的参数调用。