C variadic宏是否能够递归地扩展## __ VA_ARGS__?

wcy*_*wcy 1 c macros gcc variadic

variadic宏提到了关于gcc的VA_ARGS.

我做了以下实验.

#define EVAL(f,...) eval(f,build_args(args,__VA_ARGS__ , args_end))
Run Code Online (Sandbox Code Playgroud)

EVAL(f,a) // => eval(f,build_args(args,a, args_end))
EVAL(f,a,b) // => eval(f,build_args(args,a,b, args_end))
Run Code Online (Sandbox Code Playgroud)

到目前为止这么好,但是

EVAL(f) // => eval(f,build_args(args, , args_end))
Run Code Online (Sandbox Code Playgroud)

我必须提供至少一个参数,我根据手册解决问题,使用'##'.

#define EVAL(f,...) eval(f,build_args(args,##__VA_ARGS__ , args_end))
EVAL(f,a) // => eval(f,build_args(args,a, args_end))
EVAL(f,a,b) // => eval(f,build_args(args,a,b, args_end))
EVAL(f) // => eval(f,build_args(args, args_end))
Run Code Online (Sandbox Code Playgroud)

到目前为止这么好,但是

#define EVAL(f,...) eval(f,build_args(args,##__VA_ARGS__ , args_end))
EVAL(f,EVAL(g,a)) // => eval(f,build_args(args,EVAL(g,a) , args_end))
Run Code Online (Sandbox Code Playgroud)

我们可以看到第二个EVAL没有扩展,但没有'##',第二个EVAL是扩展的.

#define EVAL(f,...) eval(f,build_args(args,##__VA_ARGS__ , args_end))
EVAL(f,EVAL(g,a)) // => eval(f,build_args(args,
                  //          eval(g,build_args(args,a , args_end), 
                  //                 args_end))
Run Code Online (Sandbox Code Playgroud)

所以情况就是这样

  1. 没有##,我必须在东方提供一个参数,但宏可以递归扩展.
  2. with ##,零参数可以,但宏不能递归计算.

我可以同时解决这两个问题吗?

小智 5

你能试试吗?

#define _build_args(args,f,...) eval(f,build_args(args,__VA_ARGS__))
#define EVAL(f...) _build_args(args,f,args_end)
Run Code Online (Sandbox Code Playgroud)

它似乎对我有用,因为:

EVAL(f,a)
EVAL(f,a,b)
EVAL(f)
EVAL(f,EVAL(g,a))
Run Code Online (Sandbox Code Playgroud)

给出:

eval(f,build_args(args,a,args_end))
eval(f,build_args(args,a,b,args_end))
eval(f,build_args(args,args_end))
eval(f,build_args(args,eval(g,build_args(args,a,args_end)),args_end))
Run Code Online (Sandbox Code Playgroud)