
[...]
Indeed, you are using a Map when what you really want is a Tuple, since your keys are integers. Here's the version I would have written:
#include <boost/hana/integral_constant.hpp> #include <boost/hana/range.hpp> #include <boost/hana/tuple.hpp> using namespace boost::hana;
static constexpr int map_size = 100;
void run() { constexpr auto hana_range = range(int_<0>, int_<map_size>); auto hana_tuple = unpack(hana_range, [](auto ...n) { return tuple_t<std::array<char, decltype(n)::value>...>; });
auto Array = hana_tuple[int_<69>];
// instantiate the array constexpr decltype(Array)::type arr = {{0}}; static_assert(sizeof(arr) == 69, ""); }
However, I can easily imagine another example where you actually need
Louis Dionne <ldionne.2 <at> gmail.com> writes: the
functionality of a Map. See below for performance comments.
Indeed, I used a range just to compress the code. It could have been: typedef mpl::joint_view<mpl::range_c<int, 0, 50>, mpl::range_c<int, 51, 100> > mpl_range, which would likely not work with a tuple. Btw, I couldn't find a way to combine several ranges with hana.
1. Clang generates horrible code for your example. I think the fault
is
principally on the compiler, since it generates perfect code for up to ~20 elements, and then starts emitting complete crap. I'll follow up with the Clang team about this.
I hope they'll take it up, since it's the only compiler capable of compiling this code.
2. The fault is also partially on the library, which does not compress the storage of empty types right now. Hence, your compile-time map, which contains (int_<...>, type<...>) pairs, actually has a huge sizeof, whereas it should have sizeof(char) since all those pairs are empty.
Indeed, I was able to make the runtime performance issue go away by compressing the storage of empty types in Hana pairs. I opened an issue [2] to track the progress of this feature. By the way, I consider this a high priority feature.
[...] As you can see, only your original Map example is bad, and it starts sudenly at about 30 elements, which reinforces my thinking that it's a compiler bug or quality of implementation issue. As you can see, my version using Hana Tuple is indeed 0 overhead, just like the MPL. I am confident that compressing empty types and making the Map implementation more clever should resolve the issue you presented.
I wish there was a deterministic, language enforced way, to make sure that stuff intended to be compile-time stayed as such. Relying on an optimizer isn't all that comforting in this case. Although, it maybe that the lack of constexpr lambda's makes it impossible.
Also it appears that Hana lets the compiler swallow all kinds of
code
that doesn't appear to have any practical meaning:
I understand (maybe erroneously) that a hana::map can have a useful application only if its keys are compile-time constructs, and yet I was able to compile: make_map(make_pair(1, "one"), make_pair(2, "two"));
You are correct when you state that Hana Maps require the keys to be comparable at compile-time, i.e. the comparison of two keys must return an IntegralConstant.
The above usage, which is generally meaningless, is impossible to catch at compile-time in general, because the type of the object returned by the comparison of 1 with something else may depend on that something else. In other words, we can only flag the above usage if there exists no 'x' (of any type) such that '1 == x' returns an IntegralConstant. However there is no way to assess that in general.
I am probably missing something, but can't you check that the first element of every pair going into the map is a compile-time constant. Isn't (1 == anything) either a bool or a compile-time error, whereas int_<1> == anything is always a bool_<> or error? Thanks for your more than exhaustive reply.