为什么' boost::hana::range_c '不是序列?
Why is `boost::hana::range_c` not a Sequence?
#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::tuple
和hana::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>(...)
必须创建包含...
的标签S
的Sequence
。但是,range
必须在一定间隔内包含连续的integral_constant
。因此,如果range
是Sequence
,那么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_constant
和8,3,5,10
的range
,这没有意义。另一个类似的例子是permutations
算法,说明为什么range
不能是Sequence
。permutations
算法接受一个Sequence
,并返回包含所有排列的Sequence
s的Sequence
。显然,由于range
只能容纳integral_constant
s,因此尝试创建range
s的range
是没有意义的。这样的例子比比皆是。
换句话说,range
过于专门化,无法对Sequence
概念进行建模。拥有这种专门化结构的好处是,它在编译时非常高效。缺点是它不是一个通用的容器,一些操作不能在它上面完成(比如zip
)。但是,如果您知道权衡是什么,您完全可以将range
转换为完整的序列。
- 如何创建一个版本的 boost::range::transform,该版本具有用于捕获上下文的额外参数
- Boost Range适配器制作集合
- 声明“const”“boost::range”的正确方法
- 如何使用标准迭代器使用`boost :: range`迭代器
- 如何使用boost :: range :: apapters ::通过std :: unordered_set转换
- 为什么BOOST.RANGE RANGE_BEGIN/END FREE功能对const和非const引用都重载
- 为什么 Boost.Range is_sorted不需要前向迭代器?
- itertools.tee equivalent in Boost::Range?
- boost::range::d etail::any_iterator 不能很好地与 boost::zip_iterator 一起使用
- 如何编写一个以boost::Range为参数的函数
- 如何创建一个Boost.Range来隐藏多层向量并将其公开为单个Range
- 在C++接口中使用Boost.Range
- 分区一个boost::range::转换后的范围适配器
- 使用range遍历boost::month_iterators
- boost Range库将成为下一个c++标准的一部分吗?
- Boost::range用于处理容器的内容,并将映射中的值管道到下一个进程
- c++:如何使用boost::range查找max_element
- 使用boost::range创建一个缩进算法
- Boost.Range算法,用于获取范围的第n个元素
- 我可以以非常量的方式使用 Boost.Range 索引适配器吗?