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,为不建模的类型特化为 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
。但是,它仍然必须廉价地复制(如果可复制)、移动、赋值和销毁,以便 范围适配器 不会有意外的复杂度。
默认情况下,建模 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++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
P2325R3 | C++20 | view 需要 default_initializable |
不再需要 |
LWG 3549 | C++20 | enable_view 未检测到 view_interface 的继承 |
已检测 |
P2415R2 | C++20 | 析构时间复杂度的限制过于严格 | 已放宽 |