std::ranges::view, std::ranges::enable_view, std::ranges::view_base
在标头
<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 = |
(2) | (C++20 起) |
struct
view_base {
};
|
(3) | (C++20 起) |
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_view
为 true
,而对不实现的类型特化为 false 。这些特化应当可用于常量表达式并拥有 const bool 类型。
语义要求
T
实现
view
,仅若:
-
T
的移动构造拥有常数时间复杂度,且 - 若从保有 \(\scriptsize
M\)M 个元素的
T
对象作出 \(\scriptsize N\)N 次复制与/或移动,则这 \(\scriptsize N\)N 个对象拥有 \(\scriptsize \mathcal{O}{(N+M)}\)𝓞(N+M) 时间复杂度析构(这蕴含被移动的view
对象拥有 \(\scriptsize \mathcal{O}{(1)}\)𝓞(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
的类型为可复制或非占有。然而,它必须仍然有廉价的复制(凡在可能时)、移动及析构,以令范围适配器不会拥有不期待的复杂度。
实现 movable
和 range
的类型默认被认为是视图,若它公开且无歧义地派生自 view_base
或恰好一个 ranges::view_interface 的特化。
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
P2325R3 | C++20 | view 要求 default_initializable
|
不要求 |
LWG 3549 | C++20 | enable_view 不检测来自 view_interface
的继承
|
检测 |
P2415R2 | C++20 | 析构的时间复杂度上的限制过于严格 | 已放松 |