这个概念体现了什么想法?具体来说,它的实例如何“安全地转换为视图”以及为什么我想要这样的转换?这里的“安全”到底意味着什么?
任意范围can只需执行以下操作即可将其转换为视图:
template <input_range R>
auto into_view(R&& r) {
return ref_view(r);
}
但这并不是一个好主意。如果我们有一个右值范围(无论它是否是视图),那么现在我们正在引用它,因此如果我们保留结果视图太久,这可能会悬而未决。
一般来说,我们不想保留对view
是 - a 的点view
范围适配器通过值而不是引用来保存它们。但一般来说,我们不想按值保存非视图范围,因为复制这些范围的成本很高。
What viewable_range
所做的是将范围集限制为我们可以转换为视图而无需额外担心悬空的范围:
-
view
s 应该总是按值 - 所以是左值view
只是一个viewable_range
如果它是可复制的。右值view
总是一个viewable_range
(因为view
s 必须是可移动的)。
- an lvalue non-
view
范围始终是viewable_range
因为我们采取ref_view
在这种情况下。这当然有可能出现悬空,但我们采用左值,所以这是更安全的情况。
- an rvalue non-
view
range 最初被拒绝(因为我们唯一的选择是ref_view
在这种情况下我们不想引用),但将开始被捕获为owning_view
(as of P2415 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2415r2.html).
所以基本上,唯一不是可视范围的是左值不可复制视图,因为希望避免引用视图。
Do you always use viewable_range
to constrain universal forwarding reference? (i.e. the only chance T to be deduced to lvalue reference type.) This is the case for standard range adaptor (closure) objects.
否。仅当您想要对转发引用执行的操作是将其转换为视图并存储结果视图时。范围适配器可以做到这一点,但算法不需要这样做 - 因此它们不应该使用该约束(标准库算法都不会这样做)。
在 C++23 中,范围适配器(闭包)对象被修改为将范围作为第一个参数。从那时起,viewable_range 概念还有其他用途吗?
The term范围适配器闭包对象很宽松,因为现在我们可以拥有用户定义的范围适配器闭包对象(P2387 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2387r3.html),我们无法真正执行他们实际所做的事情。
但标准库范围适配器闭包对象仍然需要viewable_range
(通过all_t
).
对于应用程序开发,何时使用viewable_range
代替view
or range
?
这实际上与(2)是同一个问题。如果您想要获取任何范围并将其转换为要存储的视图,您可以使用viewable_range
- 所以当你编写范围适配器时。