1

Given a hana::tuple specifying the shape of a N-dimensional box, (e.g. (2,3,2) in 3D) at compile time, I would like to generate a tuple of tuples with all coordinate combinations at compile time. (0,0,0) (0,0,1) (0,1,0) (0,1,1) (0,2,0) (0,2,1) (1,0,0) (1,0,1) (1,1,0) (1,1,1) (1,2,0) (1,2,1)

The question is related to another one I posted a few days ago (link) but reformulated for hana. I seem to have trouble coming up with an algorithm which respects the immutability of the hana::tuple object. I fail to recognize what combination of hana algorithms will allow me to generate a recursive call and also collect the returned tuples at the same time.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Teodor Nikolov
  • 783
  • 7
  • 14
  • 1
    Do you need the coordinates themselves to be available at compile-time (to e.g. instantiate a template with them)? What are you trying to achieve? If you're just trying to optimize a loop, don't. Use a `std::array` with normal loops and the optimizer will do its job. Otherwise, use `hana::cartesian_product`. – Louis Dionne Aug 03 '16 at 01:02
  • I need the coordinates at compile time to instantiate a template. But the template is only needed because I was doing what you guessed - manually unrolling a nested loop. At first I implemented my algorithm using `std::array`. However I wasn't sure how much I should trust the compiler. That is why I attempted to implement another version using meta-programming and check if there is any significant performance benefit. – Teodor Nikolov Aug 03 '16 at 06:55

1 Answers1

1

Per your comment, you were only trying to perform loop unrolling. You may want to measure both ways, but usually the compiler will do an immensely better job than you at optimizing these things when the array bounds are known. You may actually significantly slow down or bloat your program by forcing loop unrolling.

That being said, if that's what you want to do, here's how you can do it:

#include <boost/hana.hpp>
namespace hana = boost::hana;

template <int ...> struct your_template { };

int main() {
    auto xs = hana::to_tuple(hana::range_c<int, 0, 10>); // [0, ..., 9]
    auto ys = hana::to_tuple(hana::range_c<int, 0, 10>); // [0, ..., 9]
    auto zs = hana::to_tuple(hana::range_c<int, 0, 10>); // [0, ..., 9]

    auto coords = hana::cartesian_product(hana::make_tuple(xs, ys, zs));
    hana::for_each(coords, hana::fuse([](auto x, auto y, auto z) {
        your_template<decltype(x)::value, decltype(y)::value, decltype(z)::value> foo;
        (void)foo;
    }));
}

Be aware, however, that generating the cartesian product is pretty nasty at compile-time, as you're generating a huge tuple. The above, for example, takes about 10s to compile on my box.

Louis Dionne
  • 3,104
  • 1
  • 15
  • 35