使用Jens spelled out 的简化版本,一种可能的方法如下所述。
E_ 用于注入参数,而I_ 用于导致间接调用宏。 V_ 需要添加额外的间接级别,some compilers 似乎需要这样做。
#define V_(...) __VA_ARGS__
#define I_(M,...) V_(M(__VA_ARGS__))
#define E_() _,
现在,假设您需要一个宏 MAC 来处理 0、1 或 2 个参数:
MAC(1, 2);
MAC(1);
MAC();
一种可能的实现可能如下所示:
#define MAC_X(_2,_1,X,...) MAC_##X
#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,2,_))(__VA_ARGS__))
#define MAC_2(...) function_for_2(__VA_ARGS__)
#define MAC_1(...) function_for_1(__VA_ARGS__)
#define MAC_0(...) function_for_0(__VA_ARGS__)
#define MAC_Y(_1,Y,...) MAC_##Y
#define MAC__(...) I_(MAC_Y, E_ __VA_ARGS__ () 0, 1)(__VA_ARGS__)
将其扩展为 3 个参数相对简单。唯一的麻烦是检测 1 或 0 个参数,它们不会改变:
-#define MAC_X(_2,_1,X,...) MAC_##X
-#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,2,_))(__VA_ARGS__))
+#define MAC_X(_3,_2,_1,X,...) MAC_##X
+#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,3,2,_))(__VA_ARGS__))
+#define MAC_3(...) function_for_3(__VA_ARGS__)
#define MAC_2(...) function_for_2(__VA_ARGS__)
对于超过 1 个参数,MAC 宏扩展为 MAC_2(或 MAC_3)。但是,对于 1 或 0 个参数,MAC 宏扩展为 MAC__。
MAC__ 宏应用 Jens 的技巧来检测是否传递了 1 个或 0 个参数。它使用E_ 辅助宏来做到这一点,并在E_ 和() 之间注入它的参数,这将导致它被调用。如果有 0 个参数,则调用 E_,并注入一个参数。注入的参数导致0 成为MAC_Y 选择的第二个参数。如果有 1 个参数,E_ 不会展开。 MAC_Y 的第一个参数变为E_ ... () 0(其中... 是第一个参数),MAC_Y 的第二个参数是1。这允许MAC_Y 调用MAC_0 或MAC_1。