std::ranges::view, std::ranges::enable_view, std::ranges::view_base
来自 cppreference.com
在头文件 <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。用户可以将
enable_view
特化为 true,用于模拟 view
的 cv 无限定的程序定义类型,以及 false,用于不模拟 view
的类型。此类特化必须 在常量表达式中可用,并且类型为 const bool.内容 |
[编辑] 语义要求
1) 仅当
T
满足以下条件时,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
。但是,它在复制(如果可复制)、移动、赋值和销毁时仍然必须廉价,以便范围适配器不会出现意外的复杂性。
默认情况下,如果一个类型模拟了movable
和range
,并且它公开且明确地派生自view_base
,或者正好一个std::ranges::view_interface的特化,那么它就被认为是一个视图。
[编辑] 示例
一个最小的视图。
#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 | 对销毁时间复杂度的限制过于严格 | 放宽 |