# std::ranges::views::take, std::ranges::take_view

< cpp‎ | ranges

定义于头文件 `<ranges>` |  |
template< ranges::view V > class take_view : public ranges::view_interface<take_view<V>> | (1) | (C++20 起)
namespace views { inline constexpr /*unspecified*/ take = /*unspecified*/; } | (2) | (C++20 起)

1) 范围适配器，表示来自底层序列的始于开端终于给定边界的元素的 `view` 。
2) `views::take` 是一个范围适配器对象。表达式 views::take(e, f) 产生表示来自 e 的首 f 个元素的视图。结果不一定是 `take_view` 。

它表达式等价于（其中 `T` 为 std::remove_cvref_t<decltype((e))> 而 `D` 为 ranges::range_difference_t<decltype((e))> ）：

- ((void)f, static_cast<T>(e)) ，若 `T` 为 ranges::empty_view ，除了 e 与 f 的求值具有不确定顺序；
- U(ranges::begin(e), ranges::begin(e) + std::min<D>(ranges::distance(e), f)) ，若 `T` 是 std::span、 std::basic_string_view 或 ranges::subrange 的实现 `random_access_range` 及 `sized_range` 的特化，其中 `U` 为

  - std::span<typename T::element_type> ，若 `T` 为 std::span 的特化；
  - T ，若 `T` 为 std::basic_string_view 的特化；
  - ranges::subrange<ranges::iterator_t<T>> ，若 `T` 为 ranges::subrange 的特化；

- ranges::iota_view(*ranges::begin(e), *(ranges::begin(e) + std::min<D>(ranges::distance(e), f))) ，若 `T` 为 ranges::iota_view 实现 `random_access_range` 及 `sized_range` 的特化；
- 否则为 take_view(e, f) 。

所有情况下 decltype((f)) 必须实现 std::convertible_to<D> 。

### 表达式等价

表达式 e 表达式等价于表达式 f ，若 e 与 f 拥有相同效果，均为潜在抛出或均非潜在抛出（即 noexcept(e) == noexcept(f) ），且均为常量子表达式或均非常量子表达式。

### 成员函数

(构造函数) (C++20) | 构造 `take_view` (公开成员函数)
base (C++20) | 返回底层（适配的）视图的副本 (公开成员函数)
begin (C++20) | 返回指向起始的迭代器 (公开成员函数)
end (C++20) | 返回指向末尾的迭代器或哨位 (公开成员函数)
size (C++20) | 返回元素数，只要底层（适配的）范围满足 `sized_range` (公开成员函数)
##### 继承自 std::ranges::view_interface
empty (C++20) | 返回视图是否为空。若视图满足 `forward_range` 则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)
operator bool (C++20) | 返回派生视图是否为非空。若 ranges::empty 可应用于它则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)
data (C++20) | 返回派生视图的数据的地址。若视图的迭代器类型满足 `contiguous_iterator` 则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)
front (C++20) | 返回派生视图中的首元素。若视图满足 `forward_range` 则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)
back (C++20) | 返回派生视图中的末元素。若视图满足 `bidirectional_range` 与 `common_range` 则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)
operator[] (C++20) | 返回派生视图中的第 n 个元素。若视图满足 `random_access_range` 则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)

### 推导指引

### 嵌套类

sentinel (C++20) | 哨位类型 (仅用于阐释的成员类模板)

### 辅助模板

template<class T> inline constexpr bool enable_borrowed_range<std::ranges::take_view<T>> = std::ranges::enable_borrowed_range<T>; |  | (C++20 起)

`std::ranges::enable_borrowed_range` 的此特化使得 `take_view` 在底层类型实现 `borrowed_range` 时实现它。

### 示例

    #include <algorithm>
    #include <iostream>
    #include <ranges>

    auto print = [](char x) { std::cout << x; };

    int main()
    {
        constexpr char pi[] { '3', '.', '1', '4', '1', '5', '9', '2' };

        std::ranges::for_each(pi | std::ranges::views::take(6), print);
        std::cout << '\n';

        std::ranges::for_each(std::ranges::take_view{pi, 42}, print); // safely takes only 8 chars
        std::cout << '\n';
    }

输出：

    3.1415
    3.141592

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 3494 | C++20 | `take_view` 决不是 `borrowed_range` | 若底层视图是 `borrowed_range` 则它是
LWG 3407 | C++20 | `views::take` 有时无法构造具大小随机访问范围 | 调整结果类型使构造始终合法

### 参阅

views::counted (C++20) | 从迭代器和计数创建子范围 (定制点对象)
ranges::take_while_view views::take_while (C++20) | 由另一 `view` 的到首个谓词返回 `false` 为止的起始元素组成的 `view` (类模板) (范围适配器对象)
ranges::copy_n (C++20) | 将一定数目的元素复制到一个新的位置 (niebloid)