# std::ranges::views::elements, std::ranges::elements_view

< cpp‎ | ranges

定义于头文件 `<ranges>` |  |
template< ranges::input_range V, std::size_t N > requires view<V> && __HasTupleElement<ranges::range_value_t<V>, N> && __HasTupleElement<std::remove_reference_t<ranges::range_reference_t<V>>, N> && __ReturnableElement<<ranges::range_reference_t<V>, N> class elements_view : public ranges::view_interface<elements_view<V, N>>; | (1) | (C++20 起)
namespace views { inline constexpr /*unspecified*/ elements = /*unspecified*/; } | (2) | (C++20 起)
调用签名 |  |
template< ranges::viewable_range R > requires /* see below */ constexpr ranges::view auto elements<N>( R&& r ); |  |
辅助概念 |  |
template< class T, std::size_t N > concept __HasTupleElement = // 仅用于阐释 requires(T t) { typename std::tuple_size<T>::type; requires N < std::tuple_size_v<T>; typename std::tuple_element_t<N, T>; { std::get<N>(t) } -> std::convertible_to<const std::tuple_element_t<N, T>&>; }; | (3) | (C++20 起)
template< class T, std::size_t N > concept __ReturnableElement = // 仅用于阐释 std::is_reference_v<T> || std::move_constructible<std::tuple_element_t<N, T>>; | (4) | (C++20 起)

1) 接收元组式值的 `view` ，并产生值类型为适配视图的值类型的第 `N` 元素的视图。
2) `views::elements` 的每个特化均为范围适配器对象。对于任何适合的表达式 e 与常量表达式 M表达式 views​::​elements<M>(e) 表达式等价于 elements_view<views​::​all_t<decltype((e))>, M>{e} 。
3) 确保底层视图的元素是元组式值。
4) 确保不能返回悬垂引用。

`elements_view` 在底层视图 `V` 实现 `random_access_range`、 `bidirectional_range`、 `forward_range`、 `input_range`、 `common_range` 及 `sized_range` 时实现对应的概念。

### 表达式等价

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

### 成员函数

(构造函数) (C++20) | 构造 `elements_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>` 的公开成员函数)
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>` 的公开成员函数)

### 嵌套类

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

### 辅助模板

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

`std::ranges::enable_borrowed_range` 的此特化使得 `elements_view` 在底层视图满足 `borrowed_range` 时满足它。

### 示例

    #include <iostream>
    #include <ranges>
    #include <tuple>
    #include <vector>

    int main()
    {
        const std::vector<std::tuple<int, char, std::string>> vt {
            {1, 'A', "α"},
            {2, 'B', "β"},
            {3, 'C', "γ"},
            {4, 'D', "δ"},
            {5, 'E', "ε"},
        };

        for (int const e: std::views::elements<0>(vt)) { std::cout << e << ' '; }
        std::cout << '\n';
        for (char const e: std::views::elements<1>(vt)) { std::cout << e << ' '; }
        std::cout << '\n';
        for (std::string const& e: std::views::elements<2>(vt)) { std::cout << e << ' '; }
        std::cout << '\n';
    }

输出：

    1 2 3 4 5
    A B C D E
    α β γ δ ε

### 缺陷报告

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

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 3494 | C++20 | `elements_view` 始终不是 `borrowed_range` | 若底层视图是 `borrowed_range` 则它是
LWG 3502 | C++20 | 能从 `elements_view` 获得悬垂引用 | 禁止这种用法

### 参阅

ranges::keys_view views::keys (C++20) | 选取 pair 式值组成的 `view` 并产生每个 pair 的第一元素的 `view` (类模板) (范围适配器对象)
ranges::values_view views::values (C++20) | 选取 pair 式值组成的 `view` 并产生每个 pair 的第二元素的 `view` (类模板) (范围适配器对象)
slice | valarray 的 BLAS 式切片：起始下标、长度、跨度 (类)