“viewable_range”概念有什么意义?

Ced*_*Sun 5 c++ c++-concepts range-v3 c++20

[范围.细化]

\n
\n

viewable_\xc2\xadrange 概念指定了可以安全转换为视图的范围类型的要求。

\n
\n

它的强制实现粗略地表明,如果满足以下任一条件,则range进一步满足viewable_range

\n
    \n
  1. 它只是一个视图,例如std::string_view,或
  2. \n
  3. 它是一个左值引用(即使它的引用删除类型不是视图),例如std::vector<int>&,或
  4. \n
  5. 它是可移动对象类型(即不是引用类型),例如std::vector<int>
  6. \n
\n

我的问题是:

\n
    \n
  1. 这个概念体现了什么想法?具体来说,它的实例如何“安全地转换为视图”以及为什么我想要这样的转换?这里的“安全”到底意味着什么?
  2. \n
  3. 您总是使用viewable_range约束通用参考吗?(即被推导为左值引用类型的唯一机会T。)这是标准范围适配器(闭包)对象的情况。
  4. \n
  5. range在 C++23 中,范围适配器(闭包)对象被修改为采用 a作为第一个参数。viewable_range从那时起概念还有其他用途吗?
  6. \n
  7. 对于应用程序开发,什么时候使用orviewable_range代替?viewrange
  8. \n
\n

Bar*_*rry 5

这个概念体现了什么想法?具体来说,它的实例如何“安全地转换为视图”以及为什么我想要这样的转换?这里的“安全”到底意味着什么?

任何范围都可以转换为视图,只需执行以下操作:

template <input_range R>
auto into_view(R&& r) {
    return ref_view(r);
}
Run Code Online (Sandbox Code Playgroud)

但这并不是一个好主意。如果我们有一个右值范围(无论它是否是视图),那么现在我们正在引用它,因此如果我们保留结果视图太久,这可能会悬而未决。

一般来说,我们不想保留对views 的引用 - a 的要点view是范围适配器通过值而不是引用来保存它们。但一般来说,我们不想按值保存非视图范围,因为复制这些范围的成本很高。

所做viewable_range的是将范围集限制为我们可以隐藏到视图而无需额外担心悬空的范围:

  • views 应该始终按值排列 - 因此左值仅在可复制时view才是 a 。viewable_range右值view始终是 a viewable_range(因为views 必须是可移动的)。
  • view范围始终是 a,因为在这种情况下viewable_range我们采用 a 。ref_view这当然有可能出现悬空,但我们采用左值,所以这是更安全的情况。
  • view范围最初被拒绝(因为我们唯一的选择是ref_view并且我们不想在这种情况下引用),但将开始被捕获为owning_view(从P2415开始)。

所以基本上,唯一不是可视范围的是左值不可复制视图,因为希望避免引用视图。

您是否总是使用viewable_range约束通用转发参考?(即 T 被推导为左值引用类型的唯一机会。)这是标准范围适配器(闭包)对象的情况。

否。仅当您想要对转发引用执行的操作是将其转换为视图并存储结果视图时。范围适配器可以做到这一点,但算法不需要这样做 - 因此它们不应该使用该约束(标准库算法都不会这样做)。

在 C++23 中,范围适配器(闭包)对象被修改为将范围作为第一个参数。从那时起,viewable_range 概念还有其他用途吗?

术语“范围适配器闭包对象”被放宽了,因为现在我们可以拥有用户定义的范围适配器闭包对象(P2387),我们无法真正强制执行它们实际执行的操作。

但标准库范围适配器闭包对象仍然需要viewable_range(通过all_t)。

对于应用程序开发,什么时候使用orviewable_range代替?viewrange

这实际上与(2)是同一个问题。如果您想要获取任何范围并将其转换为要存储的视图,则viewable_range在编写范围适配器时可以使用 -so 。