考虑以下用户风格的x-macro:
#define PRIMES_X(func) \
func(2) \
func(3) \
func(5)
我们可以使用它以前三个素数重复调用传入的宏func
。例如:
#define MAKE_FUNC(num) void foo ## num();
PRIMES_X(MAKE_FUNC)
会声明返回空白的函数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()
吗?
答案 0 :(得分:2)
您可以插入另一个级别的宏扩展(df[paste0('A_', seq(10, 90, 10))] <-
lapply(seq(10, 90, 10), function(i) (df$A * i + df$B * (100 - i)) / 100)
# > df
# A B A_10 A_20 A_30 A_40 A_50 A_60 A_70 A_80 A_90
# 1 0.80 0.9000 0.89000 0.88000 0.87000 0.86000 0.8500 0.84000 0.83000 0.82000 0.81000
# 2 0.99 0.8800 0.89100 0.90200 0.91300 0.92400 0.9350 0.94600 0.95700 0.96800 0.97900
# 3 0.70 0.9658 0.93922 0.91264 0.88606 0.85948 0.8329 0.80632 0.77974 0.75316 0.72658
# 4 0.65 0.6684 0.66656 0.66472 0.66288 0.66104 0.6592 0.65736 0.65552 0.65368 0.65184
)。
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
答案 1 :(得分:1)
Yunnosch的答案很好,但是为了进一步旋转X宏的疯狂,你也可以在列表中使用宏调用,而不是在它之外的包装宏。这样做的好处是你可以将“变量”从列表传递给被调用的宏。
我想这可能有一些用处 - 假设您希望使用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;}