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

时间:2015-10-16 19:29:03

标签: c++ boost-hana

#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::ziphana::tuple上使用hana::range_c,但hana::range_c不被视为序列,是hana::zip的要求。这个决定背后的原因是什么?我如何(惯用)在尊重这个决定的同时实现我的目标?

1 个答案:

答案 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。因此,如果rangeSequence,则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 Sequencerange。显然,由于integral_constant只能保留range,因此尝试创建range range s是没有意义的。像这样的例子比比皆是。

换句话说,Sequence s太专业化,无法模拟zip概念。拥有这样一个专门结构的好处是它具有非常高的编译时间。缺点是它不是通用容器,并且无法对其进行某些操作(如range)。但是,如果您知道权衡取舍,则可以完全取{{1}}并将其转换为完整序列。