Boost hana получить индекс первого соответствия

Поэтому я пытаюсь сделать библиотеку, используя boost::hana для этого требуется функциональность, чтобы получить индекс элемента на основе значения:

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>

Есть ли возможный способ сделать это? Еще лучше, это уже в hana и я не знаю об этом?

Спасибо за поддержку!

3

Решение

Хана не предоставляет алгоритм, чтобы сделать это из коробки. Если это кажется желанной функцией, я мог бы добавить такой алгоритм довольно легко. Это, вероятно, подходит как часть интерфейса любого Iterable, поскольку Iterables — это те последовательности, для которых индексы имеют смысл.

В настоящее время я бы подошел к чему-то очень близкому к тому, что @cv_and_he предложил в своем комментарии:

#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() { }

Несколько замечаний по поводу приведенного выше кода. Во-первых, в Хане индексы должны быть неотрицательными, поэтому, вероятно, будет хорошей идеей использовать тип без знака. Во-вторых, я использую hana::drop_while вместо hana::take_whileпотому что первое требует только Iterableв то время как последний требует Sequence, Хотя может показаться, что я делаю больше работы (вычисляю размер в два раза), оказывается, что вычисление размера большинства последовательностей, с которыми вы столкнетесь, очень быстрое, так что на самом деле это не проблема. Наконец, я прилагаю hana::size(hana::drop_while(...)) в decltype, который гарантирует, что никакая работа не будет выполнена во время выполнения.

4

Другие решения

Как насчет использования 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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector