命名空间
变体
操作

std::ranges::view, std::ranges::enable_view, std::ranges::view_base

来自 cppreference.cn
< cpp‎ | ranges
 
 
范围库 (Ranges library)
范围适配器 (Range adaptors)
 
定义于头文件 <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 起)
1) view 概念指定了在构造范围适配器管道时具有合适语义属性的 range 类型所需的要求。
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_viewtrue,为不建模的类型特化为 false。此类特化必须 在常量表达式中可用,并且类型为 const bool
3)view_base 派生使得 range 类型能够建模 view

目录

[编辑] 语义要求

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 类型的例子有

可复制容器,例如 std::vector<std::string> 通常不满足 view 的语义要求,因为复制容器会复制所有元素,这不能在常数时间内完成。

虽然视图最初被描述为廉价可复制且不拥有数据的范围,但类型不要求是可复制的或不拥有数据以建模 view。但是,它仍然必须廉价地复制(如果可复制)、移动、赋值和销毁,以便 范围适配器 不会有意外的复杂度。

默认情况下,建模 movablerange 的类型,如果它公开且明确地派生自 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 析构时间复杂度的限制过于严格 已放宽