Search code examples
cgccmacrosvariadic

Is C variadic macro able to expand ##__VA_ARGS__ recursively?


variadic macro mentioned about VA_ARGS for gcc.

I did the following experiment.

#define EVAL(f,...) eval(f,build_args(args,__VA_ARGS__ , args_end))

And

EVAL(f,a) // => eval(f,build_args(args,a, args_end))
EVAL(f,a,b) // => eval(f,build_args(args,a,b, args_end))

So far so good, but

EVAL(f) // => eval(f,build_args(args, , args_end))

I must supply at least one argument, I solve the problem according to manual, use '##'.

#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))

So far so good, but

#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))

We can see the second EVAL is not expanded, but without '##', the second EVAL is expaned.

#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))

So here is the situation

  1. without ##, I have to supply at east one argument, but macro can be recursively expanded.
  2. with ##, zero argument is OK but macro cannot be evaluated recursively.

Can I have both problems solved at the same time?


Solution

  • Can you please try this ?

    #define _build_args(args,f,...) eval(f,build_args(args,__VA_ARGS__))
    #define EVAL(f...) _build_args(args,f,args_end)
    

    It seems to work on my side because :

    EVAL(f,a)
    EVAL(f,a,b)
    EVAL(f)
    EVAL(f,EVAL(g,a))
    

    gives :

    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))