Boost Hana获取第一个匹配项的索引

Rus*_*ene 3 c++ boost template-meta-programming c++11 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>
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?更好的是,它已经存在了hana,我不知道吗?

感谢您的支持!

Lou*_*nne 5

Hana没有提供开箱即用的算法。如果它似乎是非常需要的功能,则可以相当容易地添加这样的算法。它可能很适合作为any的接口的一部分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() { }
Run Code Online (Sandbox Code Playgroud)

有关上述代码的一些注意事项。首先,在Hana中要求索引必须为非负数,因此使用无符号类型可能是一个好主意。其次,我使用hana::drop_while代替hana::take_while,因为前者只需要一个Iterable,而后者则需要一个Sequence。虽然看起来我在做更多的工作(两次计算大小),但事实证明,计算将遇到的大多数序列的大小非常快,因此这并不是真正的问题。最后,我将hana::size(hana::drop_while(...))in 封装起来decltype,以确保在运行时不会进行任何工作。

  • 我很想在Hana中看到`index_of`或类似的东西。 (3认同)
  • 如果您不将其封装在`decltype`中,`hana :: drop_while`将在运行时创建一个新序列。对于您当前的用例,这可能不是问题,但是请考虑一下,如果您的`iterable`包含`std :: string`s会发生什么。然后,运行`hana :: drop_while`将创建这些字符串的副本,这是完全没有用的。将整个内容包含在“ decltype”中可确保不执行任何运行时工作。 (2认同)