std::ranges::view, std::ranges::enable_view, std::ranges::view_base

来自cppreference.com
< cpp‎ | ranges
 
 
范围库
范围访问
范围转换器
(C++23)
范围原语



悬垂迭代器处理
范围概念
视图

范围工厂
适配器
范围生成器
范围适配器对象
范围适配器闭包对象
辅助项
 
在标头 <ranges> 定义
template<class T>
concept view = ranges::range<T> && std::movable<T> && ranges::enable_view<T>;
(1) (C++20 起)
template<class T>

inline constexpr bool enable_view =

    std::derived_from<T, view_base> || /*is-derived-from-view-interface*/<T>;
(2) (C++20 起)
struct view_base { };
(3) (C++20 起)
1) view 概念指定拥有适合用于构造范围适配器管道的语义属性的 range 类型(例如一对迭代器或按需创建其元素的生成器 range
2) enable_view 变量模板用于指示 range 是否为 view/*is-derived-from-view-interface*/<T>true 当且仅当 T 准确拥有一个对于某类型 U 的公开基类 ranges::view_interface<U> ,且 T 无任何对于其他类型 V 的基类 ranges::view_interface<V>
用户可对要实现 view 的无 cv 限定的程序定义类型特化 enable_viewtrue ,而对不实现的类型特化为 false 。这些特化应当可用于常量表达式并拥有 const bool 类型。
3)view_base 派生会允许 range 类型实现 view

语义要求

1) T 实现 view ,仅若:
  • T 的移动构造拥有常数时间复杂度,且
  • 若从保有 M 个元素的 T 对象作出 N 次复制与/或移动,则这 N 个对象拥有 𝓞(N+M) 时间复杂度析构(这蕴含被移动的 view 对象拥有 𝓞(1) 析构),且
  • std::copy_constructible<T>false ,或 T 的复制构造拥有常数时间复杂度,且
  • std::copyable<T>false ,或 T 拥有不多于析构后随复制构造的时间复杂度。

注解

view 类型的示例为:

  • 包装一对迭代器的 range 类型,例如 std::ranges::subrange<I>
  • 通过 std::shared_ptr 持有其元素并与所有副本共享所有权的 range 类型。
  • 按需生成其元素的 range 类型,例如 std::ranges::iota_view

诸如 std::vector<std::string> 的可复制容器通常不符合 view 的语义要求,因为复制容器会复制其所有元素,这无法在常数时间内完成。

视图原先被描述成可廉价复制并且为非占有的范围,不过不要求要实现 view 的类型为可复制或非占有。然而,它必须仍然有廉价的复制(凡在可能时)、移动及析构,以令范围适配器不会拥有不期待的复杂度。

实现 movablerange 的类型默认被认为是视图,若它公开且无歧义地派生自 view_base 或恰好一个 ranges::view_interface 的特化。

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
P2325R3 C++20 view 要求 default_initializable 不要求
LWG 3549 C++20 enable_view 不检测来自 view_interface 的继承 检测
P2415R2 C++20 析构的时间复杂度上的限制过于严格 已放松