#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::zip
和hana::tuple
上使用hana::range_c
,但hana::range_c
不被视为序列,是hana::zip
的要求。这个决定背后的原因是什么?我如何(惯用)在尊重这个决定的同时实现我的目标?
答案 0 :(得分:5)
首先,有几种解决方案:
解决方案1
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];
// ...
});
解决方案2
auto types = hana::make_tuple(std::forward<T>(args)...);
hana::size_c<sizeof...(T)>.times.with_index([&](auto i) {
auto& x = types[i];
// ...
});
解决方案3
args
解决方案(1)的缺点是制作每个zip
的副本,因为range
会返回一系列序列,而Hana中的所有内容都是按值计算的。由于这可能不是您想要的,您应该在解决方案(2)和(3)之间选择您喜欢的任何一种,它们实际上是等价的。
现在,Sequence
未对Sequence
概念建模的原因是因为这没有意义。 Sequence
概念要求我们能够使用hana::make
函数创建任意Sequence
。因此,对于任何S
代码hana::make<S>(...)
,Sequence
必须创建包含S
的{{1}}代码...
。但是,range
必须在某个时间间隔内包含连续的integral_constant
。因此,如果range
是Sequence
,则hana::make<hana::range_tag>(...)
应该包含...
所有的内容,如果range
不是...
,则会打破integral_constant
的不变量连续的hana::make<hana::range_tag>(hana::int_c<8>, hana::int_c<3>,
hana::int_c<5>, hana::int_c<10>)
s。考虑例如
range
这应该是包含integral_constant
s 8,3,5,10
的{{1}},这是没有意义的。另一个显示range
不能是Sequence
的原因的类似示例是permutations
算法。 permutations
算法需要Sequence
并返回包含所有排列的Sequence
Sequence
个range
。显然,由于integral_constant
只能保留range
,因此尝试创建range
range
s是没有意义的。像这样的例子比比皆是。
换句话说,Sequence
s太专业化,无法模拟zip
概念。拥有这样一个专门结构的好处是它具有非常高的编译时间。缺点是它不是通用容器,并且无法对其进行某些操作(如range
)。但是,如果您知道权衡取舍,则可以完全取{{1}}并将其转换为完整序列。