Hacker News new | past | comments | ask | show | jobs | submit login
Boost Histogram: Fast multidimensional histogram, convenient interface for C++14 (github.com)
38 points by ingve 9 days ago | hide | past | web | favorite | 18 comments

How many people would immediately understand the code sample:

    auto h = make_histogram(
      axis::regular<>(6, -1.0, 2.0, "x")

    // fill histogram
    auto data = { -10, -0.4, 1.1, 0.3, 1.3 };
    std::for_each(data.begin(), data.end(), std::ref(h));
I would have to Google what std::ref does again, and then I have to understand why it is used, etc. The code is short and readable, but understanding it still takes time.

    for (double x : { -10, -0.4, 1.1, 0.3, 1.3 })
Shorter, better.

Yeah, for_each is a great idea and if you don't have C++'s complicated reference / copy object model it works very well. But it's not as nice as an actual for loop.

Thanks for the feedback, I am going to update the example in the readme. The point was that boost::histogram plays nicely with the C++ stdlib algorithms, but that seems to be distracting.

I argue that nobody could possibly understand this snippet without reference to the source, even if they have C++ chapter and verse committed to memory. |auto| with a factory function sucks because you have to look up the return type. The source code actually uses |auto| as the declared return type which sucks again, they have made their library much harder to read and understand and saved themselves only a tiny amount of typing. Then it’s not even a little obvious that |histogram| is a unary function. You have to read it to see why that works and if it works naturally or because the argument can be implicitly constructed. Basically I hate this.

This would be a lot more readable without the deduced return type and if it had a named function for the fill that could be called from a lambda or bound function.

> |auto| with a factory function sucks because you have to look up the return type.

It's funny how we never hear Ocaml or Haskell programmers complaining about type inference.

Without reading the post, I read this as make a histogram with 6 bins in range –1 to 2 with name x. Then sort data into the histogram. What I don’t understand is the relevance of x, or why not just have a h.fill() function.

Labels are metadata. You can attach arbitrary metadata to each axis or no metadata at all. The metadata is sometimes useful to keep track what each axis range was representing. For example, if you load a serialized histogram into your program that someone else generated.

Here is an example which demonstrates the usefulness of labels: https://raw.githubusercontent.com/boostorg/histogram/develop...

The design choice of using operator() or a fill() method was hotly debated. In the bigger picture of things, operator() is better because then 1D histogram have the same fill syntax as the accumulators from Boost::accumulators.

If you had to Google what `std::ref` is then you aren't a very proficient C++ developer - but if you had seen the actual example rather than the stripped down one in the GitHub repo, you would probably understand straightaway - https://www.boost.org/doc/libs/1_70_0/libs/histogram/doc/htm...

> If you had to Google what `std::ref` is then you aren't a very proficient C++ developer

I can't recall the last time I saw someone use std::ref. Maybe once in the past 5 years, and I think I deleted it after I fixed something else. One of the good things about C++ is that you don't have to use all of it (in fact, you probably should not use all of it).

It's very useful when you want to pass something by reference into a function that takes a varadic template parameters and uses perfect forwarding, i.e. https://godbolt.org/z/xlmwFw

    template <typename... Args> void foo( Args&&... args ) {
        whiz( std::forward<Args>( args )... );


    int i = 5;
    double k = 2.3;

    foo( std::ref( i ), k ); // take i by ref, k by value
I've also seen it a lot with std::thread, and basically anything else that takes a callable/functor where the developer chose not to use lambda's with reference captures.

Would agree that it isn't a major language feature, but I would expect competent developers to at least know about it and why you would want to/have to use it (if they had worked with a compiler that had >=C++11 support).

You’d need them for std::future/async/thread, which is my primary use case.

I agree that not needing to use all of C++ is one of the best things about it. (Opt-in vs opt-out.)

love this lib, been using it for awhile, but when i was trying to get it running with ROS Indigo i had to backport Boost Variant ...never want to do that again

And that is the main problem with boost. If you want any of it, you have to live with all of it.

Some Boost libraries have little or no dependency on other libraries, e.g. boost::mp11. In the past, our libraries used to be very interdependent, but we recognize that this is an issue and nowadays try to decouple the libraries so that you can install only the parts you need.

We even provide a tool to help with that: https://www.boost.org/doc/libs/1_70_0/tools/bcp/doc/html/ind...

boost::histogram currently depends directly on 8 other boost libraries, but some of those (e.g. boost::variant) pull in a huge number of other libraries, so in total it is 29. I am working on reducing the dependencies in the upcoming versions.

Pretty cool to see that boost admits that this is an issue and works on decoupling things. I look forward to see improvements here.

That's not true.

Glad to hear it! What was the problem with Boost Variant exactly?

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact