std::ranges::view, std::ranges::enable_view, std::ranges::view_base
来自 cppreference.cn
定义于头文件 <ranges> |
||
template<class T> concept view = ranges::range<T> && std::movable<T> && ranges::enable_view<T>; |
(1) | (自 C++20 起) |
template<class T> constexpr bool enable_view = |
(2) | (自 C++20 起) |
struct view_base { }; |
(3) | (自 C++20 起) |
2)
用户可以为建模
enable_view
变量模板用于指示 range
是否为 view
。 /*is-derived-from-view-interface*/<T> 当且仅当 T
恰好有一个公共基类 ranges::view_interface<U> (对于某些类型 U
)时,且 T
没有类型为 ranges::view_interface<V> 的基类(对于任何其他类型 V
)时,为 true。用户可以为建模
view
的 cv 限定的程序定义类型将 enable_view
特化为 true,并为不建模 view
的类型特化为 false。此类特化必须是 可在常量表达式中使用的,并且具有类型 const bool。目录 |
[编辑] 语义要求
1)
T
建模 view
仅当T
的移动构造具有常数时间复杂度,且- 如果从持有 M 个元素的
T
对象复制和/或移动了 N 个副本,则这些 N 个对象的销毁具有 𝓞(N+M) 的复杂度(这意味着已移动源view
对象的销毁具有 𝓞(1) 的复杂度),且 - 要么 std::copy_constructible<T> 为 false,要么
T
的复制构造具有常数时间复杂度,且 - 要么 std::copyable<T> 为 false,要么
T
的复制赋值的时间复杂度不高于销毁后跟复制构造。
[编辑] 特化
对于以下标准模板的所有特化,enable_view
的特化定义为 true
(自 C++26 起) |
[编辑] 注释
view
类型的示例包括:
- 包装一对迭代器的
range
类型,例如 std::ranges::subrange<I>。 - 通过 std::shared_ptr 持有其元素并与其所有副本共享所有权的
range
类型。 - 按需生成其元素的
range
类型,例如 std::ranges::iota_view。
诸如 std::vector<std::string> 之类的可复制容器通常不符合 view
的语义要求,因为复制容器会复制所有元素,而这不能在常数时间内完成。
虽然视图最初被描述为廉价可复制且非拥有的范围,但类型不一定需要是可复制的或非拥有的才能建模 view
。但是,它仍然必须是廉价复制(如果可复制)、移动、赋值和销毁的,以便 范围适配器 不会具有意外的复杂度。
默认情况下,如果类型公开且明确地派生自 view_base
,或者恰好是一个 std::ranges::view_interface 的特化,则建模 movable
和 range
的类型被认为是视图。
[编辑] 示例
最小视图。
#include <ranges> struct ArchetypalView : std::ranges::view_interface<ArchetypalView> { int* begin(); int* end(); }; static_assert(std::ranges::view<ArchetypalView>);
[编辑] 缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
P2325R3 | C++20 | view 要求 default_initializable |
不要求 |
LWG 3549 | C++20 | enable_view 未检测到从 view_interface 的继承 |
检测到 |
P2415R2 | C++20 | 对销毁的时间复杂度的限制过于严格 | 已放宽 |