C++20 Ranges在VS2019 v16.10中全面完成

C++20 Ranges在VS2019 v16.10中全面完成

作者:BlogUpdater |  时间:2021-06-12 |  浏览:1083 |  评论已关闭 条评论

今天我们很高兴地宣布,我们在VS2019 v16.10中完成了标准库中的C++20 Ranges特性。在去年(2020年)年中的时候,我们官宣了在VS2019 v16.6中的第一个可用且用户可见的Ranges部分,涓涓细流加速成一股涌流,最终部分现已就位。这代表了过去两年开源贡献者的大量工作。

具有讽刺意味的是,Ranges对于标准库来说并不是什么新鲜事。STL算法总是对元素范围进行操作,这些元素的边界由表示第一个元素的迭代器和指向经过计算的元素序列末尾的迭代器表示。 C++20 Ranges的新颖之处在于,我们认识到直接作为抽象传递Ranges而不是传递迭代器对所带来的表达能力——消除了将迭代器传递到不同Ranges作为错误来源——并且对Ranges的操作可以组合更多,相比于对其元素的操作来说,这样更加容易。

哪些组件构成了C++20 Ranges设计?
Ranges首先放宽了旧的C++迭代器的设计,允许表示元素序列末尾的标记与表示开始的迭代器具有不同的类型。这可以用来表达简单的概念,例如由指向字符的指针和分隔符标记界定的范围,当指针指向 ‘\0’ 时,该分隔符与指向字符的指针相等。 一个 Range 是任何表达式 meow 使得 std::ranges::begin(meow) 和 std::ranges::end(meow) 返回一个迭代器和一个哨兵(sentinel)。

Ranges库使用C++概念表达了对类型的谓词(“这是一个双向迭代器吗?”)和类型之间的关系(“这是一个有效的迭代器和哨兵对吗?”)。 Ranges是C++标准库中新的概念语言特性的第一次使用——而且是相当广泛的使用。 概念具有很好的表现力,因为它们允许类型要求的规范,以及在较小程度上对参数值的先决条件,直接作为语法出现在代码中,而不是作为英文散文出现在文档中。(有关C++概念的更多讨论,请参阅“Visual Studio 2019 版本 16.3 中的 C++20 概念”。)

Ranges在命名空间std::ranges中添加了一组算法——命名空间std中定义的算法的镜像。 这些算法受概念约束,与std中的同级不同,它们接受范围参数和迭代器-哨兵对参数,其中哨兵和迭代器类型不同。

Ranges也毫不奇怪地向标准库添加了一系列范围。 标准将这些拆分为创建范围的工厂:
> std::views::iota(0, 42) 是从 0 到但不包括 42 的整数范围,
> std::views::istream_view(std::cin) 是从std::cin读取的以空格分隔的整数范围

将基础范围的元素转换为新范围的适配器:
> std::views::filter(my_vec, [](const auto& x) { return x % 2 == 0; }) 是仅包含 my_vec 偶数元素的范围,
> std::views::transform(my_vec, [](const auto& x) { return 3 * x; }) 是值 3k 的元素范围,其中 k 是 my_vec 的对应元素的值。

范围适配器通常最好被认为是惰性的、可组合的算法,因为它们在你开始迭代它们之前不起作用,并且它们是从范围到范围的函数。 我们可以将上面两个例子组合成:

例如,要获取由值是 my_vec 偶数元素值的三倍的元素组成的范围。 该设计甚至提供了一种管道语法来促进这种组合,使用 | 提供左侧范围作为右侧范围适配器的输入:

使用算法做等效的工作需要将中间和最终结果存储在某种容器中,像这样的适配器组合通过一次工作元素来避免这种情况。

这个实现从哪里来?
一个10 ~ 20页的提案描述了一个典型的 STL 特性,WG21 将其完善为规范以合并到 C++标准中。 P0896R4 “单一范围提案” 大约有 230 页。似乎这还不够,我们对 Ranges 实施的跟踪问题记录了 Ranges 实施中涵盖的 22 个后续提案(设计更改)和 35 个 LWG 问题(错误修复)。我们的实施计划从 2019 年 5 月 13 日开始的“实施 common_reference 和 common_type 更改”(STL 开源之前的四个内部 PR 之一)开始,通过另外 99 个以“Define __cpp_lib_ranges [功能测试宏]”,2021 年 3 月 18 日。虽然我们确实借鉴了范围技术规范库的原型设计经验以提供指导,但 STL 实现几乎完全是完全重写,仅重用了一些测试用例。

这无疑是迄今为止最大的单一标准库功能,我们无法表达我们对C++社区众多成员所做的所有工作的感激之情,这些工作帮助实现了它。我们要亲自感谢 AdamBucior、ahanamuk、barcharcraz、BillyONEal、bkentel、CaseyCarter、cbezault、cpplearner、fsb4000、futuarmo、MahmoudGSaleh、miscco、mnatsuhara、statementreply、StephanTLavavej、SuperWig 和 timcong 的代码、代码审查意见或 MSVC 范围的问题报告。就我个人而言,我的 Ranges 之旅始于六年前的本月在堪萨斯州莱内萨举行的 WG21 会议。作为一名失业的 C++ 爱好者,对 Eric Niebler 的 N4128“标准库的范围”中的设计感到非常兴奋,我从不相信我会在接下来的六年中通过标准化过程一直到今天的交付来研究该设计产品。

我今天可以试试吗?
是的,这就是重点!
请尝试一下可用的组件,我们会继续提供它们。 不要忘记下载(或更新到)Visual Studio 2019 版本 16.10; 早期版本中存在部分但并非全部范围设计。 请注意,WG21 正在处理 C++20 的一些重大更改,其中三个直接影响范围。 你可以期待对 (1) std::ranges::split_view / std::views::split 的更改,WG21 自发布 C++20 以来对其进行了很大程度的重新设计,(2) std::ranges::join_view / std:: views::join 已被调整为可在更多情况下使用,并且 (3) std::ranges::view 概念本身将失去对默认构造的要求,允许范围适配器更有效地适应不存在的基础范围以及通过生成不可默认构造的结果视图来默认构造。

总结
是时候接受点C++里的新东西了:Ranges。
(还是明天再说吧)

最后
Microsoft Visual C++团队的博客是我非常喜欢的博客之一,里面有很多关于Visual C++的知识和最新开发进展。大浪淘沙,如果你对Visual C++这门古老的技术还是那么感兴趣,则可以经常去他们那(或者我这)逛逛。
本文来自:《C++20 Ranges are complete in Visual Studio 2019 version 16.10》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

标签:

评论已关闭。