:-) The macrology is a bit grody and my DO implementation doesn't extend past 3 args.
#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++)