在 x-macro 定义中使用宏作为参数
Using a macro as an argument in an x-macro definition
考虑以下用户风格 x-macro:
#define PRIMES_X(func) \
func(2) \
func(3) \
func(5)
我们可以使用它来调用传入的宏 func
重复前三个质数。例如:
#define MAKE_FUNC(num) void foo ## num();
PRIMES_X(MAKE_FUNC)
将声明返回 void 的函数 foo2()
、foo3()
和 foo5()
.
到目前为止,还不错。现在假设我想在 x-macro 本身的定义中使用一个宏作为参数,如下所示:
#define MAX_PRIME 5
#define PRIMES_X(func) \
func(2) \
func(3) \
func(MAX_PRIME)
它不起作用,因为 MAKE_FUNC
现在将尝试声明 void fooMAX_PRIME()
,因为(我想)标记连接发生时没有扩展 MAX_PRIME
。
我可以解决这个问题,让它像以前一样声明 foo5()
吗?
您可以插入另一层宏展开(下图PRIMES_X2
)。
#define MAKE_FUNC(num) void foo ## num();
#define MAX_PRIME 5
#define PRIMES_X(func) PRIMES_X2(func, MAX_PRIME)
#define PRIMES_X2(func, maxPrimePar) \
func(2) \
func(3) \
func(maxPrimePar)
PRIMES_X(MAKE_FUNC)
输出 gcc -E
:
void foo2(); void foo3(); void foo5();
Yunnosch 的回答很好,但要进一步旋转 X 宏的疯狂程度,您还可以在列表内调用宏而不是在列表外调用包装器宏。这样做的好处是您可以将 "variables" 从列表传递给被调用的宏。
我想这可能会有一些用处 - 例如,假设您希望使用 X 宏来声明不同类型的函数?
示例:
#define MAX_PRIME 5
#define CREATE_FUNC(func, ret_type, param) func(ret_type, param)
#define PRIMES_X(func) \
CREATE_FUNC(func, int, 2) \
CREATE_FUNC(func, void, 3) \
CREATE_FUNC(func, double, MAX_PRIME) \
#define MAKE_FUNC(ret_type, num) ret_type foo ## num(void);
PRIMES_X(MAKE_FUNC)
#undef MAKE_FUNC
调试代码以检查函数是否确实获得了预期的原型:
int main(void)
{
(void)foo2();
foo3();
(void)foo5();
}
int foo2 (void){ return 0;}
void foo3 (void){}
double foo5 (void){ return 0.0;}
考虑以下用户风格 x-macro:
#define PRIMES_X(func) \
func(2) \
func(3) \
func(5)
我们可以使用它来调用传入的宏 func
重复前三个质数。例如:
#define MAKE_FUNC(num) void foo ## num();
PRIMES_X(MAKE_FUNC)
将声明返回 void 的函数 foo2()
、foo3()
和 foo5()
.
到目前为止,还不错。现在假设我想在 x-macro 本身的定义中使用一个宏作为参数,如下所示:
#define MAX_PRIME 5
#define PRIMES_X(func) \
func(2) \
func(3) \
func(MAX_PRIME)
它不起作用,因为 MAKE_FUNC
现在将尝试声明 void fooMAX_PRIME()
,因为(我想)标记连接发生时没有扩展 MAX_PRIME
。
我可以解决这个问题,让它像以前一样声明 foo5()
吗?
您可以插入另一层宏展开(下图PRIMES_X2
)。
#define MAKE_FUNC(num) void foo ## num();
#define MAX_PRIME 5
#define PRIMES_X(func) PRIMES_X2(func, MAX_PRIME)
#define PRIMES_X2(func, maxPrimePar) \
func(2) \
func(3) \
func(maxPrimePar)
PRIMES_X(MAKE_FUNC)
输出 gcc -E
:
void foo2(); void foo3(); void foo5();
Yunnosch 的回答很好,但要进一步旋转 X 宏的疯狂程度,您还可以在列表内调用宏而不是在列表外调用包装器宏。这样做的好处是您可以将 "variables" 从列表传递给被调用的宏。
我想这可能会有一些用处 - 例如,假设您希望使用 X 宏来声明不同类型的函数?
示例:
#define MAX_PRIME 5
#define CREATE_FUNC(func, ret_type, param) func(ret_type, param)
#define PRIMES_X(func) \
CREATE_FUNC(func, int, 2) \
CREATE_FUNC(func, void, 3) \
CREATE_FUNC(func, double, MAX_PRIME) \
#define MAKE_FUNC(ret_type, num) ret_type foo ## num(void);
PRIMES_X(MAKE_FUNC)
#undef MAKE_FUNC
调试代码以检查函数是否确实获得了预期的原型:
int main(void)
{
(void)foo2();
foo3();
(void)foo5();
}
int foo2 (void){ return 0;}
void foo3 (void){}
double foo5 (void){ return 0.0;}