Boost hana 获取第一个匹配项的索引
Boost hana get index of first matching
所以我正在尝试使用 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
而我不知道?
感谢支持!
#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;
}
Hana 不提供开箱即用的算法。如果它看起来像一个非常需要的功能,我可以很容易地添加这样一个算法。它可能很适合作为任何 Iterable
接口的一部分,因为 Iterable
是那些索引有意义的序列。
目前,我会选择与@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 中索引必须是非负的,所以使用无符号类型可能是个好主意。其次,我使用hana::drop_while
而不是hana::take_while
,因为前者只需要一个Iterable
,而后者需要一个Sequence
。虽然看起来我在做更多的工作(两次计算大小),但事实证明,计算您将遇到的大多数序列的大小非常快,所以这并不是一个真正的问题。最后,我将 hana::size(hana::drop_while(...))
包含在 decltype
中,以确保在运行时不会完成任何工作。
所以我正在尝试使用 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
而我不知道?
感谢支持!
#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;
}
Hana 不提供开箱即用的算法。如果它看起来像一个非常需要的功能,我可以很容易地添加这样一个算法。它可能很适合作为任何 Iterable
接口的一部分,因为 Iterable
是那些索引有意义的序列。
目前,我会选择与@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 中索引必须是非负的,所以使用无符号类型可能是个好主意。其次,我使用hana::drop_while
而不是hana::take_while
,因为前者只需要一个Iterable
,而后者需要一个Sequence
。虽然看起来我在做更多的工作(两次计算大小),但事实证明,计算您将遇到的大多数序列的大小非常快,所以这并不是一个真正的问题。最后,我将 hana::size(hana::drop_while(...))
包含在 decltype
中,以确保在运行时不会完成任何工作。