/ / Zwiększ hana uzyskaj indeks pierwszych dopasowań - c ++, c ++ 11, boost, template-meta-programming, boost-hana

Zwiększ hana uzyskaj indeks pierwszych dopasowań - c ++, c ++ 11, boost, template-meta-programming, boost-hana

Próbuję więc użyć biblioteki boost::hana wymaga funkcjonalności, aby uzyskać indeks elementu na podstawie wartości:

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>

Czy jest możliwy sposób na zrobienie tego? Jeszcze lepiej, czy już jest hana i nie wiem o tym?

Dzięki za wsparcie!

Odpowiedzi:

4 dla odpowiedzi № 1

Hana nie zapewnia algorytmu do tego celupo wyjęciu z pudełka. Jeśli wydaje się, że jest to bardzo pożądana funkcja, mogę dość łatwo dodać taki algorytm. Prawdopodobnie pasowałoby to jako część interfejsu dowolnego Iterable, od Iterables są tymi sekwencjami, dla których wskaźniki są znaczące.

Na razie chciałbym pójść z czymś bardzo bliskim do tego, co @cv_and_he zaproponował w swoim komentarzu:

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

Kilka uwag na temat powyższego kodu. Po pierwsze, wskaźniki muszą być nieujemne w Hanie, więc prawdopodobnie dobrym pomysłem będzie użycie typu bez znaku. Po drugie, używam hana::drop_while zamiast hana::take_while, ponieważ ten pierwszy wymaga tylko Iterable, podczas gdy druga wymaga Sequence. Chociaż może się wydawać, że robię więcej pracy(obliczając dwukrotnie rozmiar), okazuje się, że obliczanie rozmiaru większości sekwencji, które napotkasz, jest bardzo szybkie, więc nie jest to naprawdę problemem. Wreszcie zamykam plik hana::size(hana::drop_while(...)) w decltype, co zapewnia, że ​​żadna praca nie zostanie wykonana w czasie wykonywania.


0 dla odpowiedzi nr 2

Jak o użyciu 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;
}