Cool!
I've often thought about the best way to do this, and your suggestion is compelling. I'm going to try it out.
I've often thought about the best way to do this, and your suggestion is compelling. I'm going to try it out.
#define DO(...) for(long long _a[]={__VA_ARGS__,1,1,1,1},i=0;i<*_a;++i) \
for(long long j=0;j<_a[1];++j)for(long long k=0;k<_a[2];++k)
It doesn't seem bad to me, and it'd be pretty easy to extend or add asserts to catch when you introduce a fourth arg.gcc also appears smart enough to remove the unnecessary loads, so I'm going to keep playing with it.
#define mkmacro(func, ...) mkmacro_(func, VA_NUM_ARGS(__VA_ARGS__))
#define mkmacro_(func, nargs) mkmacro__(func, nargs)
#define mkmacro__(func, nargs) func ## nargs
#define DO(...) mkmacro(DO, __VA_ARGS__)(__VA_ARGS__)
#define DO1(n) for(I i=0;i<(n); i++)
#define DO2(m,n) DO1(m) for(I j=0;j<(n);j++)
#define DO3(l,m,n) DO2(l,m) for(I k=0;k<(n);k++)I did some testing and seems like this generates much less code at least with clang (with -O3 -fomit-frame-pointer) than geocar's much briefer solution!
#define VA_NUM_ARGS(...) \
VA_NUM_ARGS_IMPL(__VA_ARGS__,5,4,3,2,1)
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,N,...) N
#define mkmacro(func, ...) \
mkmacro_(func, VA_NUM_ARGS(__VA_ARGS__))
#define mkmacro_(func, nargs) mkmacro__(func, nargs)
#define mkmacro__(func, nargs) func ## nargs
#define DO(...) mkmacro(DO, __VA_ARGS__)(__VA_ARGS__)
#define DO1(n) for(I i=0;i<(n); i++)
#define DO2(m,n) DO1(m) for(I j=0;j<(n);j++)
#define DO3(l,m,n) DO2(l,m) for(I k=0;k<(n);k++)