I have a number of nested loops with small sizes I, J, ... known at compile time, e.g.
for(int i = 0; i < I; ++i) {
for(int j = 0; j < J; ++j) {
// ...
// do sth with (i,j,...)
}
}
I need to unroll the loops using the sizes I, J, ... in such a way that I can use each coordinate combination at compile time.
To clarify, consider the following structure and take 2 nested loops with sizes I = 2, J = 3.
template<int... I>
struct C {
static void f() {
// do sth
}
};
I can not use the indices i, j (similar to above) to index the structure C since they are not known at compile time. However what I would like to generate is exactly what would have been the case had I been allowed to use the indices, e.g.
C<0,0>::f();
C<0,1>::f();
C<0,2>::f();
C<1,0>::f();
C<1,1>::f();
C<1,2>::f();
I am not particularly concerned with the order of call generations as long as all combinations are produced. The generation mechanism should generalize to arbitrary number of nested loops.
You can do this by instantiating templates in a tree-like manner, keeping track of the nodes currently visited.
Usage is pretty simple:
On Clang this prints:
Live Demo
You could make this more generic so that you can inject the loop body into the class through a lambda, but the above solution should do if you only want to do this once and don't want to pull in other dependencies like
boost::hana
. Here's a possible implementation of the more generic version (you could improve it with perfect forwarding and the like):You would use this like so:
Live Demo
Here's a quick version I mocked up with
boost::hana
. There are likely better ways to do this, but this should give you an idea of what can be done.