范围TS成语和神秘的汽车&&

Nic*_*las 9 c++ c++20

在预范围TS代码中,我可能会执行以下操作来获得对ForwardIterator值的(可能可修改的)引用:

auto &val = *it;
Run Code Online (Sandbox Code Playgroud)

这也将用于for这种迭代器的基于范围的循环:

for(auto &val : some_range)
Run Code Online (Sandbox Code Playgroud)

但是,在C++ 20和基于范围TS的代码中,我auto&&在这些位置看到了很多用法.我auto&&从语言的角度理解正在做的事情.我不明白为什么它在这些地方使用,什么时候auto&应该工作得很好?这种性质的大多数代码都不转发引用,那么为什么它使用转发引用来捕获它?

Nic*_*las 12

这个成语正在被使用,因为Range TS和C++ 20-equivalent实际上需要这个成语.这个要求的原因与代理迭代器现在是所有类别的迭代器的合法构造的事实有关.

代理迭代器operator*不会返回value_type&; 它返回该对象的prvalue 作用像一个参考.因此,如果您尝试存储对值的引用,则auto&代码将无法使用代理迭代器进行编译.

Range TS的迭代器概念从不要求返回值operator*实际上是语言引用.可读概念仅要求返回值可转换为value_type.可写概念仅要求value_type可以将a分配给返回值.

因此auto&&,现在必须使用在Range功能下从各种迭代器获取引用的代码,它可以绑定到prvalues而不需要它们const.因此,在处理范围时,如果要获取值的非const引用,auto&&则是最方便的方法.如果您只想要一个const参考,您可以继续使用const auto &.


请注意,auto&&它还处理直接value_type从其中返回类型的prvalues的迭代器operator*.显然这些只对Readable迭代器有用,但它们非常有用.最简单的例子是在一些整数上计数范围的迭代器.迭代器返回一个int,而不是对某些内存的引用.由于没有返回语言引用的硬性要求,因此这些迭代器可以是Range TS中的RandomAccessIterators.

这样的迭代器对正则表达式匹配也有意义.当前regex_iterator返回对内部对象的引用; 这是成为ForwardIterator的必要条件.相反,它可以通过进行operator*搜索并将匹配对象作为prvalue返回来小得多.但旧系统不允许这样做.

给定这样的迭代器,auto&不能用于捕获其结果的"引用".

  • 最后但并非最不重要的是,我不认为其引用运算符返回迭代器的*值类型*的prvalue为"代理迭代器"的迭代器.我更喜欢将该类称为"prvalue迭代器".他们还需要使用`auto &&`或`const auto &`来绑定取消引用的结果,但不要涉及"真正的"代理迭代器需要解决的其他机制(`iter_move`,`iter_swap`).支持C++中的"智能引用". (2认同)
  • 哦:我还应该指出,使用转发参考并不是绝对必要的.给定一个迭代器`it`,`std :: iter_reference_t <decltype(it)> foo =*it;`总是有效的.所以即使是讨厌`auto`的异教徒也可以使用Ranges;) (2认同)