Namespaces
Variants

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

来自 zh.cppreference.net
 
 
范围库
范围适配器
 
定义于头文件 <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 指定了一个范围类型的需求,该类型具有适用于构造范围适配器管道的适当语义属性。
2) 变量模板 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。

3) 从 view_base 派生可使 范围类型符合 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 概念。然而,它仍然必须满足廉价复制(若可复制)、移动、赋值和销毁的要求,以确保 范围适配器 不会出现预期之外的复杂度。

默认情况下,若某个类型同时满足 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 对析构时间复杂度限制过于严格 已放宽