5
#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::tupleand上使用hana::range_c,但hana::range_c不被认为是Sequence,这是hana::zip. 这个决定背后的原因是什么?在尊重该决定的同时,我如何(惯用地)实现我的目标?

4

1 回答 1

8

首先,有几种解决方案:

解决方案 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概念要求我们能够Sequence使用该hana::make函数创建任意值。因此,对于任何Sequence标签Shana::make<S>(...)必须创建一个包含Sequence的标签。但是,a必须在某个区间内包含连续的 s。因此,如果是 a ,应该包含什么是,这打破了 a if are not contiguous s 的不变量。考虑例如S...rangeintegral_constantrangeSequencehana::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>)

这应该是一个range包含integral_constants 的8,3,5,10内容,这没有意义。另一个类似的例子说明为什么 arange不能是 aSequencepermutations算法。该permutations算法采用 aSequence并返回包含所有排列的a Sequenceof s。Sequence显然,由于 arange只能持有s,因此尝试创建 a of sintegral_constant是没有意义的。这样的例子比比皆是。rangerange

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

于 2015-10-17T01:14:40.027 回答