命名空间
变体
操作

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

来自 cppreference.com
< cpp‎ | ranges
 
 
范围库
范围适配器
 
在头文件 <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
用户可以将 enable_view 特化为 true,用于模拟 view 的 cv 无限定的程序定义类型,以及 false,用于不模拟 view 的类型。此类特化必须 在常量表达式中可用,并且类型为 const bool.
3)view_base 派生使 range 类型能够模拟 view

内容

[编辑] 语义要求

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 类型的示例包括

诸如 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++ 标准。

DR 应用于 已发布的行为 正确行为
P2325R3 C++20 view 需要default_initializable 不需要
LWG 3549 C++20 enable_view 没有检测到从 view_interface 的继承 检测到
P2415R2 C++20 对销毁时间复杂度的限制过于严格 放宽