Boost hana get index of first matching

耗尽温柔 提交于 2019-12-01 23:41:57

Hana does not provide an algorithm to do this out-of-the-box. If it seems like a much desired feature, I could add such an algorithm fairly easily. It would probably fit well as part of the interface of any Iterable, since Iterables are those sequences for which indices are meaningful.

For the time being, I would go with something very close to what @cv_and_he proposed 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 about the above code. First, indices are required to be non-negative in Hana, so it is probably a good idea to use an unsigned type. Secondly, I'm using hana::drop_while instead of hana::take_while, because the former only requires an Iterable, while the latter requires a Sequence. While it may seem like I'm doing more work (computing the size twice), it turns out that computing the size of most sequences you'll encounter is very fast, so it's not really a concern. Finally, I'm enclosing the hana::size(hana::drop_while(...)) in decltype, which ensures that no work whatsoever will be done at runtime.

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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!