为什么' boost::hana::range_c '不是序列?

Why is `boost::hana::range_c` not a Sequence?

本文关键字:range boost hana 为什么      更新时间:2023-10-16
#include <string>
#include <utility>
#include <vector>
#include <boost/hana.hpp>
namespace hana = boost::hana;
template <typename ...T>
void indexed_T_work(T&& ...args)
{
    auto indices = hana::range_c<std::size_t, 0, sizeof...(T)>;
    auto types = hana::make_tuple(std::forward<T>(args)...);
    hana::for_each(
        hana::zip(indices, types)
      , [](auto&& pair_) { /* Do index-dependent work with each `T` */ }
        );
}
int main()
{
    indexed_T_work(5, 13, std::vector<std::string>{}, 32.f, 42, "foo");
}

我想在hana::tuplehana::range_c上使用hana::zip,但hana::range_c不被认为是序列,这是hana::zip的要求。这一决定背后的原因是什么?我怎样才能(习惯性地)在尊重这个决定的同时实现我的目标?

首先,有几个解决方案:

解决方案1

auto indices = hana::to<hana::tuple_tag>(hana::range_c<std::size_t, 0, sizeof...(T)>);
auto types = hana::make_tuple(std::forward<T>(args)...);
hana::for_each(hana::zip(indices, types), hana::fuse([](auto i, auto&& x) {
    // ...
}));

解决方案2

auto indices = hana::range_c<std::size_t, 0, sizeof...(T)>;
auto types = hana::make_tuple(std::forward<T>(args)...);
hana::for_each(indices, [&](auto i) {
    auto& x = types[i];
    // ...
});
解决方案

3

auto types = hana::make_tuple(std::forward<T>(args)...);
hana::size_c<sizeof...(T)>.times.with_index([&](auto i) {
    auto& x = types[i];
    // ...
});

解决方案(1)的缺点是创建每个args的副本,因为zip返回序列的序列,而Hana中的所有内容都是按值的。由于这可能不是您想要的,您应该在解决方案(2)(3)之间选择您喜欢的解决方案,它们实际上是等效的。

现在,range s不为Sequence概念建模的原因是因为那没有意义。Sequence概念要求我们能够使用hana::make函数创建任意Sequence。因此,对于任何Sequence标签S, hana::make<S>(...)必须创建包含...的标签SSequence。但是,range必须在一定间隔内包含连续的integral_constant。因此,如果rangeSequence,那么hana::make<hana::range_tag>(...)应该包含...,如果...不是连续的integral_constant,这就打破了range的不变性。例如

hana::make<hana::range_tag>(hana::int_c<8>, hana::int_c<3>,
                            hana::int_c<5>, hana::int_c<10>)

这应该是包含integral_constant8,3,5,10range,这没有意义。另一个类似的例子是permutations算法,说明为什么range不能是Sequencepermutations算法接受一个Sequence,并返回包含所有排列的Sequence s的Sequence。显然,由于range只能容纳integral_constant s,因此尝试创建range s的range是没有意义的。这样的例子比比皆是。

换句话说,range过于专门化,无法对Sequence概念进行建模。拥有这种专门化结构的好处是,它在编译时非常高效。缺点是它不是一个通用的容器,一些操作不能在它上面完成(比如zip)。但是,如果您知道权衡是什么,您完全可以将range转换为完整的序列。