These are chat archives for boostorg/hana

29th
Jul 2016
Jonas Platte
@jplatte
Jul 29 2016 13:12
Is there a way I can make the compiler complain when the result of a function is bool instead of hana::bool_? Because right now I always get errors from somewhere inside hana::eval_if when I use it with a bool (that should be a hana::bool_) and two branches with different types (which there doesn't seem to be a very readable error message for either).
Alex Mopleen
@mopleen_twitter
Jul 29 2016 14:11
Hi all! I have a problem with ADL, could anyone take a look at it, please?
Start with this:

namespace
{
namespace hana = boost::hana;
using namespace hana::literals;

const auto mappy = hana::make_map(
hana::make_pair("foo"_s, 123),
hana::make_pair("bar"_s, 456)
);

typedef std::map<int, decltype(mappy)> BigMap;
BigMap myMap;

template <class T>
struct Struct
{
T value;
};

std::map<int, std::unique_ptr<Struct<BigMap::iterator>>> m;
}

and this doesn't work:
auto p = std::make_unique<Struct<BigMap::iterator>>();
m[0].reset(std::move(p));
Error from compiler:
/opt/gcc-5.2.0/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/unique_ptr.h:342:2: error: call to 'swap' is ambiguous
swap(std::get<0>(_M_t), __p);
^~~~
AO_LeadingIndicatorsPlugin.cpp:75:7: note: in instantiation of member function 'std::unique_ptr<(anonymous namespace)::Struct<std::_Rb_tree_iterator<std::pair<const int, const boost::hana::map<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::hana::string<'f', 'o', 'o'>, 0>, boost::hana::detail::bucket<boost::hana::string<'b', 'a', 'r'>, 1> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::string<'f', 'o', 'o'>, int>, boost::hana::pair<boost::hana::string<'b', 'a', 'r'>, int> > > > > >, std::default_delete<(anonymous namespace)::Struct<std::_Rb_tree_iterator<std::pair<const int, const boost::hana::map<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::hana::string<'f', 'o', 'o'>, 0>, boost::hana::detail::bucket<boost::hana::string<'b', 'a', 'r'>, 1> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::string<'f', 'o', 'o'>, int>, boost::hana::pair<boost::hana::string<'b', 'a', 'r'>, int> > > > > > > >::reset' requested here
m[0].reset(std::move(p));
^
/opt/gcc-5.2.0/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/algorithmfwd.h:571:5: note: candidate function [with _Tp = (anonymous namespace)::Struct<std::_Rb_tree_iterator<std::pair<const int, const boost::hana::map<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::hana::string<'f', 'o', 'o'>, 0>, boost::hana::detail::bucket<boost::hana::string<'b', 'a', 'r'>, 1> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::string<'f', 'o', 'o'>, int>, boost::hana::pair<boost::hana::string<'b', 'a', 'r'>, int> > > > > > ]
swap(_Tp&, _Tp&)
^
/opt/ao_dependencies/ExternalLibraries/boost/boost/boost/hana/detail/algorithm.hpp:23:20: note: candidate function [with T = (anonymous namespace)::Struct<std::_Rb_tree_iterator<std::pair<const int, const boost::hana::map<boost::hana::detail::hash_table<boost::hana::detail::bucket<boost::hana::string<'f', 'o', 'o'>, 0>, boost::hana::detail::bucket<boost::hana::string<'b', 'a', 'r'>, 1> >, boost::hana::basic_tuple<boost::hana::pair<boost::hana::string<'f', 'o', 'o'>, int>, boost::hana::pair<boost::hana::string<'b', 'a', 'r'>, int> > > > > >
]
constexpr void swap(T& x, T& y) {
^
Jason Rice
@ricejasonf
Jul 29 2016 15:01
@mopleen_twitter It doesn't look like std::unique_ptr::reset is supposed to take another instance of std::unique_ptr but that is unrelated to the adl issue. I managed to simplify it a little bit. This should probably be created as an issue on github. I don't know if hana::detail::swap needs to be named swap.
#include <boost/hana.hpp>
#include <memory>

namespace
{
  namespace hana = boost::hana;

  const auto mappy = hana::make_map(
    hana::make_pair(hana::int_c<0>, 123),
    hana::make_pair(hana::int_c<1>, 456)
  );

  using Mappy = decltype(mappy);
}

int main()
{
  std::unique_ptr<Mappy> uptr{};
  auto* p = new Mappy();
  uptr.reset(p);
}
Louis Dionne
@ldionne
Jul 29 2016 15:14
FWIW, it doesn’t fail on libc++
Jason Rice
@ricejasonf
Jul 29 2016 15:25
:open_mouth:
Jason Rice
@ricejasonf
Jul 29 2016 15:31

@jplatte Since hana::bool_ can be implicitly converted to bool, you could wrap the result in hana::bool_c<bool>.

#include <boost/hana.hpp>

namespace hana = boost::hana;

template <typename T>
auto check_pred(T const& t)
{
  static_assert(hana::IntegralConstant<T>::value,
    "Predicate result must be an IntegralConstant.");
  return t;
}

constexpr auto is_foo()
{
  return true;
}

constexpr auto is_bar()
{
  return hana::true_c;
}

int main()
{
  check_pred(hana::bool_c<is_bar()>);
  check_pred(hana::bool_c<is_foo()>);
}

I don't use hana::eval_if too much myself though.

Louis Dionne
@ldionne
Jul 29 2016 15:50
@ricejasonf @mopleen_twitter See #297. It will be fixed in develop and it will make it in the next release. Thanks for the bug report.
Louis Dionne
@ldionne
Jul 29 2016 16:02
@jplatte There’s no way for Hana to go into your code and make sure that functions that should return IntegralConstants actually do :-). However, I’ll provide a better error message in if_ and eval_if when the two types do not have a common type and the condition is not a compile-time Logical.
Louis Dionne
@ldionne
Jul 29 2016 16:16
@jplatte Actually, the error message was already quite telling… I get ../include/boost/hana/eval_if.hpp:63:25: error: operands to ?: have different types 'std::__cxx11::basic_string<char>' and ‘int’ on GCC, and Clang is even better.
Jonas Platte
@jplatte
Jul 29 2016 17:33
Yeah that's the error I got as well and it didn't take that long to understand, but it is weird when you expect your condition to be a hana::bool_.
I actually still don't know why I don't get that with multiple things I've tested. To be more precise, my condition looks like this: hana::count_if(values, hana::compose(hana::trait<my_trait>, hana::typeid_)) == hana::size_c<1>.
Jonas Platte
@jplatte
Jul 29 2016 17:38
I've tried hana::count_if(hana::tuple_t<types...>, hana::trait<my_trait>) == hana::size_c<1> as well, which seemed to have the same problem in the context of my library, but I couldn't reproduce the same error message with the simple constexpr example from the count_if documentation.
So I'm kind of stuck right now..
I will try to reproduce it again, not sure if I still have a test case.
Jonas Platte
@jplatte
Jul 29 2016 17:48
Actually, I don't seem to be able to reproduce it in any way right now... that's really weird, but I guess if it keeps working from now on I can't complain.
Louis Dionne
@ldionne
Jul 29 2016 19:12
Did you change your includes?
It could be that == was not hana::equal, and instead the implicit conversion to the underlying integral type.
Jonas Platte
@jplatte
Jul 29 2016 19:13
That could actually be the issue. I changed back from including individual headers to just including the main header, as that didn't seem to affect the compile times.
Louis Dionne
@ldionne
Jul 29 2016 19:28
To get ==, you have to include boost/hana/equal.hpp.
Otherwise, all sorts of weird shit happens.
Jonas Platte
@jplatte
Jul 29 2016 19:29
Okay, but like I said, I don't seem to get a difference in compile time, so I think I'll keep the include for the main header
Although compile times are a problem in general..
Louis Dionne
@ldionne
Jul 29 2016 19:29
Perhaps not the best design choice, but the dispatching code for hana::equal is quite involved and it’s not always useful (mostly in unit tests). The goal was mainly to reduce compile-times.
Just include the whole header. What’s up with compile-times?
Jonas Platte
@jplatte
Jul 29 2016 19:30
for a very simple example it takes anywhere between 2s and 6s (clang seems to be a little faster), I really don't know why it's so inconsistent, and also takes so long in general
Louis Dionne
@ldionne
Jul 29 2016 19:30
Show the example
Jonas Platte
@jplatte
Jul 29 2016 19:30
I mean an example using my library, not just hana
Louis Dionne
@ldionne
Jul 29 2016 19:31
Right.
Jonas Platte
@jplatte
Jul 29 2016 19:32
But if you think you might be able to help me out with that I can post the example code.
Louis Dionne
@ldionne
Jul 29 2016 19:34
Surely what you’re doing involves something non computationally trivial.. circular_permutation
That’s like O(2nn)
Jonas Platte
@jplatte
Jul 29 2016 19:34
Well my n's aren't that big
And I'm not even using any of the deriving code that that's used for in my example
Louis Dionne
@ldionne
Jul 29 2016 19:35
How big are your ns?
Jonas Platte
@jplatte
Jul 29 2016 19:36
Even just instantiating all the term templates and simplifying them seems to take up to 6s.
My biggest ns (amounts of terms inside a product, for circular_permutation) in the application code I originally created this library for are probably <10, definitely <15.
interestingly, right now I seem to get much less fluctuating build times.
about 2.1 seconds for clang, 2.7 for g++
Louis Dionne
@ldionne
Jul 29 2016 19:41
Note that it would be really useful if you had a simple CMake file to build your project
Jonas Platte
@jplatte
Jul 29 2016 19:41
and -0.3 seconds if I comment out the output + completely disable the generation of output functions (-DALGEBRA_CXX14_DISABLE_OUTPUT)
Well it's header-only.. And it's still a work in progress. But when I add examples and tests to the code, they'll have build scripts (probably cmake)
What I use for building at the moment is g++ -I. -Ihana/include -std=c++14 -Wall -Wextra -pedantic example.cpp
Louis Dionne
@ldionne
Jul 29 2016 19:45
Sure. Strongly consider using CMake, it’s the de-facto standard.
Jonas Platte
@jplatte
Jul 29 2016 19:45
Really? I still see autotools projects relatively often
Louis Dionne
@ldionne
Jul 29 2016 19:46
Don’t be one of those.. CMake is the way to go and more and more people are using it. You can build any CMake project in like 3 steps.
And it’ll work on any platform and you can generate IDE files and what not. Anyway it’s your project
Jonas Platte
@jplatte
Jul 29 2016 19:47
I don't plan on using autotools, but I can't say I find CMake much better.
Louis Dionne
@ldionne
Jul 29 2016 19:47
CMake (as a language) sucks donkey balls.
But you can get shit done with it easier than with anything else, and people are using it more and more.
Consider this: does Autotools give you the ability to pick between Xcode, Makefiles or Ninja for building your project?
Anyway, I’m totally sold but you do whatever suits you best.
Jonas Platte
@jplatte
Jul 29 2016 19:50
Honestly I don't know. The only alternative I would actually consider is pure Makefiles, because at least there it's obvious how to run tests as part of a build command.
The CMake test stuff seems to be badly documented and not available in older CMake versions.
But if I get it to work the way I want, there's no reason not to use it.
Louis Dionne
@ldionne
Jul 29 2016 19:51
Start from Hana’s CMake file and remove 90% of the stuff you won’t need.
Or something like that.
Jonas Platte
@jplatte
Jul 29 2016 19:52
Also I guess using CMake could allow installation of the header-files, although I'd probably encourage my users (if anyone will ever want to use this library :D) to just use my repo as a submodule
That sounds good ^^
Louis Dionne
@ldionne
Jul 29 2016 19:59
Hey you could have some kind of syntax ”x”_var = 3 instead of using var<X>(3)
Look at how Hana’s operator””_s is implemented. Or you could also use var(“x”_s) = 3 and piggyback on hana::operator””_s.
Jonas Platte
@jplatte
Jul 29 2016 20:00
I'm thinking about only having tags when creating the function objects, and supplying the values with named parameters to the eval function.
That would disallow tag-less variables, but I think that might be for the better anyway.
Louis Dionne
@ldionne
Jul 29 2016 20:01
I don’t see why a variable wouldn’t have a name. I’ve never seen an unamed variable in a mathematical expression, for sure.
And you wouldn’t ever have to declare TAG(X); again.
Jonas Platte
@jplatte
Jul 29 2016 20:02
Well, tag-less doesn't mean nameless
Now I'm curious about what you mean
Louis Dionne
@ldionne
Jul 29 2016 20:03
by what?
Jonas Platte
@jplatte
Jul 29 2016 20:03
named variables without tags
I mean, tag-less variables already have names right now
Louis Dionne
@ldionne
Jul 29 2016 20:03
Ah. Well use compile-time strings instead of tags.
Jonas Platte
@jplatte
Jul 29 2016 20:04
E.g. I can remove the tags, and it will use NoTag.
Oh, that's interesting
Louis Dionne
@ldionne
Jul 29 2016 20:04
Instead of creating your own _name_ struct, use Hana.
That’s all I’m saying.
Jonas Platte
@jplatte
Jul 29 2016 20:04
Right, I forgot compile-time strings were a thing
haven't used them before
Louis Dionne
@ldionne
Jul 29 2016 20:04
You should start :p
Jonas Platte
@jplatte
Jul 29 2016 20:06
Yeah I think I should
I think I'll try out compile-time strings as variable tags + named parameters to eval
But going back to compile times, are there any general tips you could give me? Also, in regards to eval_if, could always using an id / _ parameter help, so the compiler doesn't try to typecheck unused branches?
Jason Rice
@ricejasonf
Jul 29 2016 20:17
Jonas Platte
@jplatte
Jul 29 2016 20:46
Thanks :D
Re LTO: I've done that and it actually did increase my link times as you said in that presentation, but it was well worth it for overall build time because for some reason without LTO creating a static library that contains all my symbols took way longer (I think something around a full minute when with LTO it's more like 10s)
@ldionne ^
I did have to use -ffat-lto-objects though, not sure if I could get around that. Without it linking seemed to just not work at all..
Jason Rice
@ricejasonf
Jul 29 2016 21:02
I don't remember if that video says anything about it, but sometimes if you just want a type you can wrap an expression in decltype(blah){} which prevents anything in blah from being "used" which can end up discarding a lot of unnecessary symbol stuff.
Louis Dionne
@ldionne
Jul 29 2016 21:56
@jplatte I think making your guard lazy might help, but you would have to try it out. In C++17, if constexpr will make it faster, easier, etc..
But for now I think you should try with lazy nested eval_ifs, just to see if it helps.
Jonas Platte
@jplatte
Jul 29 2016 21:58
What do you mean by making it lazy?
Jonas Platte
@jplatte
Jul 29 2016 23:06
Also have watched the full talk. Did I understand correctly that metabench also does runtime benchmarks? In that case that completely sells me on CMake, because I also didn't really know what to do in regards to that, and having compiletime + runtime benchmarks through one dependency, a single file even, sounds really good! :)
(and those interactive graphs are really neat!)
This is going to be fun! Although now that I've also read up on C++17 I've found the C++11 - C++17 feature support list for Visual C++, and it looks horrible D:
Jonas Platte
@jplatte
Jul 29 2016 23:12
And the work project that got me the idea of building this library will have to work with Visual C++, probably 2015, so I really hope the original reason it made sense to use this kind of thing at work will disappear – which is actually a relatively likely possibility because this is all just a very time-inefficient attempt to get rid of some numerical instablities, and that attempt might well fail according to the mathematician I'm working with :D
I guess what I'm saying is that it would be useful to have it stated in the README.md that only GCC and clang are supported (and from which version on) ^^