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>
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 起) |
enable_view 用于指示一个范围是否为 view。当且仅当 /*is-derived-from-view-interface*/<T> 对于某个类型 true 恰好有一个公共基类 T,并且 ranges::view_interface<U> 对于任何其他类型 U 没有类型为 T 的基类时,ranges::view_interface<V> 为 V。
用户可以将 enable_view 特化为 true,用于符合 view 模型的无 cv 限定程序定义类型,以及将 false 用于不符合的类型。此类特化必须可在常量表达式中使用,并且类型为 const bool。
语义要求
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 | 对析构时间复杂度限制过于严格 | 已放宽 |