Boost hana gets the index of the first match

So, I'm trying to create a library with boost::hana

that requires the functionality to get the index of an element based on the value:

constexpr auto tup = boost::hana::make_tuple(3_c, boost::hana::type_c<bool>);

auto index = get_index_of_first_matching(tup, boost::hana::type_c<bool>);
//   ^^^^^ would be a boost::hana::int_<1>

      

Is there a way to do this? Better yet, is it already in hana

, and I don't know about it?

Thanks for the support!

+2


source to share


2 answers


Hana does not provide an algorithm for this out of the box. If this seems like a very desirable feature, I could add such an algorithm quite easily. It will probably work well with anyone's interface Iterable

, since Iterable

these are the sequences for which indexes make sense.

Currently, I would go with something very close to what @cv_and_he suggested in his comment:



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

template <typename Iterable, typename T>
constexpr auto index_of(Iterable const& iterable, T const& element) {
    auto size = decltype(hana::size(iterable)){};
    auto dropped = decltype(hana::size(
        hana::drop_while(iterable, hana::not_equal.to(element))
    )){};
    return size - dropped;
}

constexpr auto tuple = hana::make_tuple(hana::int_c<3>, hana::type_c<bool>);
constexpr auto index = index_of(tuple, hana::type_c<bool>);
static_assert(index == hana::size_c<1>, "");

int main() { }

      

A few notes on the above code. First, the indices must be non-negative in Han, so it is probably a good idea to use an unsigned type. Second, I use hana::drop_while

instead hana::take_while

, because the former only requires Iterable

and the latter requires Sequence

. While it might seem like I'm doing more work (calculating the size in half), it turns out that calculating the size of most of the sequences you come across is very fast, so it's not a problem. Finally, I include hana::size(hana::drop_while(...))

in decltype

, which ensures that no work is done during execution.

+4


source


How about using boost::detail::index_if

:



#include <boost/hana.hpp>

template <typename Haystack, typename Needle>
constexpr auto get_index_of_first_matching(Haystack&&, Needle&& n)
{
  using Pred = decltype(boost::hana::equal.to(n));
  using Pack = typename boost::hana::detail::make_pack<Haystack>::type;
  constexpr auto index = boost::hana::detail::index_if<Pred, Pack>::value;
  return boost::hana::int_c<index>;
}

int main()
{
  using namespace boost::hana::literals;
  constexpr auto tup = boost::hana::make_tuple(3_c, boost::hana::type_c<bool>);
  constexpr auto index = get_index_of_first_matching(tup, boost::hana::type_c<bool>);
  static_assert(index == boost::hana::int_c<1>, "index is wrong");
  return 0;
}

      

0


source







All Articles