Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic macro expansion for each token

Suppose I have a macro, a simple one that just calls a function foo for different type:

#define FOO(type) foo_##type();

In one go, let's say I want to call this thing for multiple different types. Concretely;

foo_int();
foo_float();
foo_point2d();

I want to generate above code with a macro called FOO2.

#define FOO2(args...) --fill--here

And just to be complete, FOO2(int, float, point2d) should expand into the above small code snippet. Is this possible with macros and how to do a different, separate thing for each argument in a variadic macro token pack?

I am sure a question like this is already asked. I searched for couple of other results, showing some sort of FOR_EACH macro implementation that were quite complicated and general. That's why I decided to ask for my specific use-case and started a new question.

like image 720
meguli Avatar asked May 17 '26 00:05

meguli


1 Answers

Yes, it's possible, but requires multiple macros.

#define MAP1(m,t,...) m(t)
#define MAP2(m,t,...) m(t); MAP1(m,__VA_ARGS__)
#define MAP3(m,t,...) m(t); MAP2(m,__VA_ARGS__)
// ... add more as needed ...
#define MAP(n,...) MAP##n(__VA_ARGS__)

#define FOO(type) foo_##type()
#define FOON(n, ...) MAP(n, FOO, __VA_ARGS__)

FOON(3, int, float, double);

The above will generate:

foo_int(); foo_float(); foo_double();

If you don't want to specify the number as argument, add the following:

#define FOO1(...) FOON(1, __VA_ARGS__)
#define FOO2(...) FOON(2, __VA_ARGS__)
#define FOO3(...) FOON(3, __VA_ARGS__)
// ... add more as needed ...

And now you can just do:

FOO3(int, float, double);

With a bit more work you can even make the macro work with any function name:

#define MAP1(m,f,t,...) m(f,t)
#define MAP2(m,f,t,...) m(f,t); MAP1(m,f,__VA_ARGS__)
#define MAP3(m,f,t,...) m(f,t); MAP2(m,f,__VA_ARGS__)
// ...
#define MAP(n,...) MAP##n(__VA_ARGS__)

#define CALL(funcname, type) funcname##_##type()
#define CALLN(n, funcname, ...) MAP(n, CALL, funcname, __VA_ARGS__)

#define CALL1(...) CALLN(1, __VA_ARGS__)
#define CALL2(...) CALLN(2, __VA_ARGS__)
#define CALL3(...) CALLN(3, __VA_ARGS__)
// ...

CALL1(foo, int);
CALL2(bar, float, double);
CALL3(baz, whatever, you, want);

Result:

foo_int();
bar_float(); bar_double();
baz_whatever(); baz_you(); baz_want();
like image 197
Marco Bonelli Avatar answered May 18 '26 13:05

Marco Bonelli



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!