生成视图
std::ranges::iota_view
类模板std::ranges::iota view<>是一个生成值序列的视图。这些值可以是整数,例如
-
1,2,3...
-
'a','b','c'...
或者可以使用运算符 ++ 来生成一系列指针或迭代器。
序列可能是有限的,也可能是无限的。
iota视图的主要用例是迭代值序列。
例如:
std::ranges::iota_view v1{1, 100};
for (auto val : v1) {
std::cout<<val<<'\n'; //打印这些值
}
对于类模板,还提供了范围适配器 std::views::iota(),它接受一个或两个参数,因此您也可以编写:
for (auto val : std::views::iota(1, 100)) { //迭代值 1,2,...99
std::cout <<val <<'\n'; //打印这些值 }
因为迭代器保存当前值,iota视图是一个借来的范围(它的迭代器的生命周期不依赖于视图)。如果iota视图受到限制,并且结束值与开始值具有相同的类型,则该视图为公共范围。
声明 iota 视图时,如下所示:
std::ranges::iota_view v1{1,100};
//值范围: 1,2,... 99
v1的类型被推导为std::ranges::iota view<int, int>,它创建了一个对象,该对象提供了基本API begin()和end(),生成这些值的迭代器。迭代器内部存储当前值,并在迭代器被递增时增加当前值
std::ranges::iota_view v1{1, 100};
//值范围: 1,2,... 99
auto pos = v1.begin();
//用值1初始化迭代器
std::cout <<*pos;
//打印当前值(这里是值1)
++pos;
//递增到下一个值(即,递增值到2)
std::cout <<*pos;
//打印当前值(这里是2)
因此,值的类型必须支持操作符++ 因此,像bool或std::string这样的值类型是不可能的。
注意,这个迭代器的类型取决于iota视图的实现,所以在这里使用它时必须使用auto。或者,你也可以用std::ranges::iterator t<v1>声明pos。
对于迭代器的range, value的范围是一个半开的范围,不包括结束值。
要包含结束值,可能必须增加结束值
std::ranges::iota_view letters{'a', 'z'+1}; //值: 'a', 'b',...'z'
for (auto c :letters) {
std::cout <<c<<'';
//打印这些值/字母
}
注意,这个循环的输出取决于字符集。只有当小写字母有连续的值时(就像ASCII或ISO-Latin-1或UTF-8的情况一样),视图只迭代小写字符。通过使用char8 t,您可以确保这是可移植的UTF-8字符的情况
std::ranges::iota_view letters{u8'a', u8'z'+1}; //UTF-8从a到z的值
如果没有传递结束值,则视图是无限的,并生成无限的值序列
std::ranges::iota_view v2{10L};
//无限范围,值:10L,11L,12L,…
std::ranges::iota_view<int> v3;
//无限范围,值:0,1,2,…
v3的类型是std::ranges::iota view<int,std::unreachable sentinel t,因此end()产生std::unreachable sentinel。
无限iota视图是无穷无尽的。当迭代器表示最大值并迭代到下一个值时,它调用运算符++,这通常会执行溢出,以便下一个值是值类型的最小值。如果视图有一个永远不匹配的结束值,它的行为是一样的。
当用迭代器初始化iota视图时,iota视图遍历指向底层值的迭代器。在这种情况下,成员函数size()和操作符[]的可用性取决于传递范围内对这些操作符的支持程度。您可以使用它来处理指向范围所有元素的迭代器。
std::list<int> coll{2,4,6,8,10,12,14};
//将每个元素的迭代器传递给foo()
for (const auto& pos : std::views::iota(coll.begin(), coll.end())) {
foo(pos);
}
您还可以使用它来初始化一个引用coll的所有当前元素的容器
std::ranges::iota_view itors{coll.begin(), coll.end()};
std::vector<std::ranges::iterator_t<decltype(col1)>> refColl{itors.begin(),
itors.end()};
注意,如果您跳过指定refCo1l的元素类型,则必须使用圆括号。否则,将使用两个迭代器元素初始化vector
std::vector refCol1(collItors.begin(), collItors.end());
iota view<>的最后一个构造函数提供了用于支持可以创建iota视图的子视图的通用代码,例如drop视图
//从视图中删除第一个元素的泛型函数:
auto dropFirst = [] (auto v) {
return decltype(v){++v.begin(),v.end()};
};
std::ranges::iota_view v1{1, 9};
auto v2 = dropFirst(v1); //从 2 到 9 的 iota 视图
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情”