首先,有几种解决方案:
解决方案 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) 之间选择您喜欢的任何一个,它们实际上是等效的。
现在,ranges 不模仿 Sequence 概念的原因是因为那没有意义。 Sequence 概念要求我们能够使用hana::make 函数创建任意Sequence。因此,对于任何Sequence 标签S,hana::make<S>(...) 必须创建包含... 的标签S 的Sequence。但是,range 必须在某个时间间隔内包含连续的 integral_constants。因此,如果range 是Sequence,则hana::make<hana::range_tag>(...) 应该包含... 是什么,如果... 不是连续的integral_constants,这会破坏range 的不变量。例如考虑
hana::make<hana::range_tag>(hana::int_c<8>, hana::int_c<3>,
hana::int_c<5>, hana::int_c<10>)
这应该是一个包含integral_constants 8,3,5,10 的range,这是没有意义的。另一个类似的例子说明了为什么range 不能是Sequence 是permutations 算法。 permutations 算法采用 Sequence 并返回包含所有排列的 Sequences 的 Sequence。显然,由于range 只能容纳integral_constants,因此尝试创建ranges 的range 是没有意义的。这样的例子比比皆是。
换句话说,ranges 过于专业化,无法模拟 Sequence 概念。拥有这样一个专门的结构的好处是它在编译时非常高效。缺点是它不是通用容器,不能在上面进行一些操作(比如zip)。但是,如果您知道权衡是什么,您完全可以使用 range 并将其转换为完整的序列。