These are chat archives for boostorg/hana

18th
Jan 2016
Maik Klein
@MaikKlein
Jan 18 2016 00:03
error: non-type template argument is not a constant expression
  return std::index_sequence<hana::value(index_of(iterable, elements))...>{};
                                                                                                      ^
Could it be possible that I can not use constexpr functions inside templates?
Jason Rice
@ricejasonf
Jan 18 2016 00:04
wrap it in decltype
probably just better to decltype()::value in that case
Maik Klein
@MaikKlein
Jan 18 2016 00:06
lol okay
Jason Rice
@ricejasonf
Jan 18 2016 00:06
oh wait
Maik Klein
@MaikKlein
Jan 18 2016 00:06
yeah it works that way
not quite sure why C++ can't figure that out by itself.
Jason Rice
@ricejasonf
Jan 18 2016 00:07
hana::value should return the contained std::size_tso I would think that would work
Maik Klein
@MaikKlein
Jan 18 2016 00:08
didn't work with hana::value
only with decltype()::value
Jason Rice
@ricejasonf
Jan 18 2016 00:09
oh because it is not constexpr when you call it with the parameters I guess
Maik Klein
@MaikKlein
Jan 18 2016 00:10
but I call it like this
  constexpr auto t = hana::tuple_t<int, char, double>;
  constexpr auto is = indices_of(t, hana::decltype_(1.0), hana::decltype_(1));
well c++ is has it's weird parts, I guess
Jason Rice
@ricejasonf
Jan 18 2016 00:11
yeah, inside the function the parameters are not considered constexpr
Maik Klein
@MaikKlein
Jan 18 2016 00:12
hm k
Jason Rice
@ricejasonf
Jan 18 2016 00:13
Which, I think, is probably why integral_constant even exists.
Maik Klein
@MaikKlein
Jan 18 2016 00:13
for decltype()::value?
Jason Rice
@ricejasonf
Jan 18 2016 00:14
Yeah because it stores the value as a static constexpr
This is not necessarily better, but you could also do something like hana::template_<std::index_sequence>(hana::value(foo)...)
... I think I haven't actually tried it.
Maik Klein
@MaikKlein
Jan 18 2016 00:30
how do I access an element of a tuple again? like std::get<0>(t); but in hana?
without hana literals
Jason Rice
@ricejasonf
Jan 18 2016 00:32
hana::at(list, hana::int_c<0>) or hana::at_c<0>(list)
Maik Klein
@MaikKlein
Jan 18 2016 00:33
hm
Maik Klein
@MaikKlein
Jan 18 2016 00:38
haha okay I accidentally created a basic_tuple and I couldn't use at on it
Maik Klein
@MaikKlein
Jan 18 2016 12:42
Does C++17 offer anything that will improve build times? Besides modules?
Jason Rice
@ricejasonf
Jan 18 2016 16:48
wrt to my use of hana::template_ above I forgot you can only give it hana::types and it returns a hana::type
Plus it still wouldn't work with raw integrals.
Louis Dionne
@ldionne
Jan 18 2016 19:13
@ricejasonf Regarding the issue that I get above with Clang (read of non-constexpr variable), and that you didn’t get with Clang 3.8: I can indeed confirm that Clang trunk does not give an error. I think this is a bug, and it should error out. I don’t even know how it manages to compile it, and what code it generates… The compiler is very very smart if it can compile that.
Jason Rice
@ricejasonf
Jan 18 2016 19:31
Apparently it is aware that it is empty and has the default constructor so it doesn't try to call it. ??
I wonder if the C++ standard says anything about that.
Louis Dionne
@ldionne
Jan 18 2016 19:34

Apparently it is aware that it is empty and has the default constructor so it doesn't try to call it. ??

The compiler would have to be very clever to take this into account during semantic analysis.

Jason Rice
@ricejasonf
Jan 18 2016 19:38
BTW @MaikKlein http://boostorg.github.io/hana/index.html#tutorial-appendix-constexpr has info about using arguments inside constexpr functions.
Jason Rice
@ricejasonf
Jan 18 2016 19:45
@ldionne Maybe it is assuming not side effects because it does not appear in the function body.
Louis Dionne
@ldionne
Jan 18 2016 19:48
I would say this is just a regression and they are not emitting the proper diagnostic anymore.
Jason Rice
@ricejasonf
Jan 18 2016 19:50
#include <iostream>

struct Noisy
{
    Noisy() { std::cout << "Noisy: constructed\n"; }
    Noisy(const Noisy&) { std::cout << "Noisy: copy-constructed\n"; }
    Noisy(Noisy&&) { std::cout << "Noisy: move-constructed\n"; }
    ~Noisy() { std::cout << "Noisy: destructed\n"; }
};

struct Silent { };


template<typename T>
constexpr int hello(T const) {
    return 0;
}

int main() {
   constexpr int x = hello(Silent{}); 
   constexpr int y = hello(Noisy{}); 
}
only fails for y
Louis Dionne
@ldionne
Jan 18 2016 19:51
Of course, because Silent{} is implicitly constexpr. 1 minute
Jason Rice
@ricejasonf
Jan 18 2016 19:51
oh
Yeah, if I add a constructor to Silent it explodes.
Jason Rice
@ricejasonf
Jan 18 2016 20:00
    Silent silent{};
    Noisy noisy{};
    constexpr int x = hello(silent);
    constexpr int y = hello(noisy);
Louis Dionne
@ldionne
Jan 18 2016 20:02
Yes, now that’s what should trigger the bug.
Clearly, y cannot be evaluated at compile-time
I think that is material for a bug report.
#include <iostream>

struct Noisy {
    Noisy() { std::cout << "Noisy: constructed\n"; }
    Noisy(const Noisy&) { std::cout << "Noisy: copy-constructed\n"; }
    Noisy(Noisy&&) { std::cout << "Noisy: move-constructed\n"; }
    ~Noisy() { std::cout << "Noisy: destructed\n"; }
};

struct Silent {
    constexpr Silent() { }
};

template <typename T>
constexpr int f(T) { return 0; }

int main() {
    Noisy t{}; // not constexpr
    constexpr int result = f(t);
}
Uh, well that’s pretty much a copy-paste of what you wrote above.
Anyway, do you want to fill a bug report against Clang, or shall I do it%
Jason Rice
@ricejasonf
Jan 18 2016 20:07
You can if you want.
Louis Dionne
@ldionne
Jan 18 2016 20:07
Ok.
Jason Rice
@ricejasonf
Jan 18 2016 20:08
That last snippet doesn't trigger the bug though does it?
Louis Dionne
@ldionne
Jan 18 2016 20:09
No, no.
I’ll give a link to the report when I’m done
Jason Rice
@ricejasonf
Jan 18 2016 20:10
cool
Louis Dionne
@ldionne
Jan 18 2016 20:15
Ahah! Actually, a constexpr copy constructor is still created.
But that copy constructor does not do anything, i.e. it does not read from the non-constexpr object.
So I’m thinking that the behavior is correct here.
But if you add a member to Silent, it should error out. I’m going to try.
struct Foo {
    Foo() : i{0} { }
    constexpr Foo(Foo const& other) : i{other.i} { }
    int i;
};

template <typename T>
constexpr int f(T) { return 0; }

int main() {
    Foo t{};
    constexpr int result = f(t);
}
Now, this fails with Clang trunk.
Jason Rice
@ricejasonf
Jan 18 2016 20:23
because it is actually doing something?
Louis Dionne
@ldionne
Jan 18 2016 20:25
Well, if you try it, you’ll see that it properly fails when accessing the runtime location other.i.
Which is, in our case, t.i, which is non-constexpr.
Jason Rice
@ricejasonf
Jan 18 2016 20:28
ah
Did you post a bug report?
Louis Dionne
@ldionne
Jan 18 2016 20:30
No, since I do not think it is a bug after all.
Jason Rice
@ricejasonf
Jan 18 2016 20:30
right
Louis Dionne
@ldionne
Jan 18 2016 21:53
@MaikKlein Care to post the code that’s giving you 10s compile-time with Hana?
Maik Klein
@MaikKlein
Jan 18 2016 23:38
@ldionne It's not the fault of hana, its just in general that I do much work and it adds up. The biggest time consumer in my code is https://github.com/ericniebler/range-v3 the variadic zip and concatenate seem very slow.
Louis Dionne
@ldionne
Jan 18 2016 23:39
Still, 10s seems like a lot for range-v3. I would imagine such compile-times to be achievable only with (perhaps a potential misuse of) Hana.
I’d like to see that code, if it’s not private.
Maik Klein
@MaikKlein
Jan 18 2016 23:40
I think it's even public but in a very hacky state
this is the example and the function that takes the most time is
I have also outlined the implementation here https://maikklein.github.io/2016/01/14/Entity-Component-System/
but the gist is this:
Maik Klein
@MaikKlein
Jan 18 2016 23:46
I have a tuple of containers, I filter the tuple based on some types, then I transform the 'filtered tuple of containers' to a tuple of ranges and then I zip them.
This is sort of the use case
    w.template update<position, velocity>([](auto& pos, auto& vel) {
      print(pos.x, pos.y);
      print(vel.x, vel.y);
    });
Louis Dionne
@ldionne
Jan 18 2016 23:47
Hmm.. You are sorting a tuple with a predicate that’s O(N) (index_of is O(N) unless I’m mistaken). So that means O(N^2log(N^2)).
Maik Klein
@MaikKlein
Jan 18 2016 23:47
Yes that is the first thing I optimized
now it looks like this
template<class Tup, class F, std::size_t... Indices>
auto transform_with_index(const Tup& tup, F&& f, std::index_sequence<Indices...>){
  return hana::make_tuple(f(hana::at_c<Indices>(tup))...);
}
template <typename Iterable, typename ...Ts>
constexpr auto indices_of(Iterable const& iterable, const Ts&...  elements) {
  return std::index_sequence<decltype(index_of(iterable, elements))::value...>{};
}

  template <class... Ts> auto get_rangev2() {
    auto filter = hana::tuple_t<Container<Ts>...>;
    auto ind = indices_of(comp_tup, hana::type_c<Ts>...);
    auto range_tup = transform_with_index(
        components_tuple, [](auto& v) { return ranges::view::all(v.container); }, ind);
    return hana::unpack(range_tup, ranges::view::zip);
  }
not public at the moment
I also needed to sort so that the types are in the correct order w.template update<position, velocity>([](auto& pos, auto& vel) {
but I don't have to do this with the indices version.
The invoke of the original version of get_range takes around 2 seconds on my machine, and I intend to do this often. It could easily add up to 60 seconds.
the new one takes around 1 second
and 0.6 of that is zip
Maik Klein
@MaikKlein
Jan 18 2016 23:53
I hope I am not confusing you too much here
I think I just want to do too much work
Louis Dionne
@ldionne
Jan 18 2016 23:53
You mean ranges::view::zip?
Maik Klein
@MaikKlein
Jan 18 2016 23:53
yeah
and ranges::view::all ranges::view::concatenate
Louis Dionne
@ldionne
Jan 18 2016 23:54
So you tried with “dummy” views and the Hana part is actually quite fast?
Maik Klein
@MaikKlein
Jan 18 2016 23:54
they also take some time
yes hana is really fast
Louis Dionne
@ldionne
Jan 18 2016 23:55
Well, from what I’m seeing, it should be quite fast with what you outline above. However, the sort one is going to be prohibitively slow, and part of it is a Hana QOI issue.
Maik Klein
@MaikKlein
Jan 18 2016 23:55
The only thing that was faster was my indices version because I didn't have to sort the types. But the speedup was not big.
Jason Rice
@ricejasonf
Jan 18 2016 23:56
Is this the same as that rearrange function we were talking about?
Maik Klein
@MaikKlein
Jan 18 2016 23:56
I think the speedup was not that big because I don't actually have that many types in the tuple.
Louis Dionne
@ldionne
Jan 18 2016 23:59

FWIW, I would probably use the following:

template <class... Ts>
auto get_rangev2() {
  auto filter = hana::tuple_t<Container<Ts>...>;
  auto ind = indices_of(comp_tup, hana::type_c<Ts>...);
  return hana::unpack(hana::slice(comp_tup, ind), [](auto& ...v) {
    return ranges::view::zip(ranges::view::all(v.container)...);
  });
}

Note that this will still be O(N^2) because of the indices_of function, but I don't see an easy way around it for now.

You’ll probably need to include <boost/hana/ext/std/integer_sequence.hpp>.