# std::ranges::get(std::ranges::subrange)

< cpp‎ | ranges‎ | subrange

定义于头文件 `<ranges>` |  |
template< std::size_t N, class I, class S, ranges::subrange_kind K > requires (N == 0 && std::copyable<I>) || N == 1) constexpr auto get( const ranges::subrange<I, S, K>& r ); | (1) | (C++20 起)
template< std::size_t N, class I, class S, ranges::subrange_kind K > requires (N < 2) constexpr auto get( ranges::subrange<I, S, K>&& r ); | (2) | (C++20 起)
namespace std { using ranges::get; } | (3) | (C++20 起)

1) 分别在 N == 0 或 N == 1 时从 `subrange` 左值（或 const 右值）获得迭代器或哨位。它主要为结构化绑定支持提供。
2) 同 (1) ，除了它接收非 const `subrange` 右值。
3) 将 (1-2) 导入命名空间 `std` ，这简化其使用并使得每个拥有可复制迭代器的 `subrange` 均为 pair 式类型。

### 参数

r | - | `subrange`

### 返回值

1) 当 N == 0 或 N == 1 时分别为从存储的迭代器或哨位复制构造的迭代器或哨位。
2) 同 (1) ，除了若 N == 0 且 `I` 不满足 `copyable` 则移动构造迭代器。

### 可能的实现

    template<std::size_t N, class I, class S, std::ranges::subrange_kind K>
        requires (N == 0 && std::copyable<I>) || N == 1)
    constexpr auto get(const std::ranges::subrange<I, S, K>& r)
    {
        if constexpr (N == 0)
            return r.begin();
        else
            return r.end();
    }

    template<std::size_t N, class I, class S, std::ranges::subrange_kind K>
        requires (N < 2)
    constexpr auto get(std::ranges::subrange<I, S, K>&& r)
    {
        if constexpr (N == 0)
            return r.begin(); // 可能进行移动构造
        else
            return r.end();
    }

### 示例

    #include <array>
    #include <iostream>
    #include <iterator>
    #include <ranges>

    int main()
    {
        std::array a{1, -2, 3, -4};

        std::ranges::subrange sub_a{ std::next(a.begin()), std::prev(a.end()) };

        std::cout << *std::ranges::get<0>(sub_a) << ' '  // == *(begin(a) + 1)
                  << *std::get<1>(sub_a) << '\n';        // == *(end(a) - 1)

        *std::get<0>(sub_a) = 42; // OK
    //  *std::get<2>(sub_a) = 13; // 硬错误：下标只能为 0 或 1
    }

输出：

    -2 -4

### 缺陷报告

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

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 3589 | C++20 | 若 N == 0 且 `I` 不实现 `copyable` 则 const 左值的重载非良构 | 从重载集移除它

### 参阅

结构化绑定 (C++17) | 绑定指定的名字到初始化器的子对象或元组元素
std::get(std::tuple) | 元组式访问指定的元素 (函数模板)
std::get(std::pair) (C++11) | 访问 `pair` 的一个元素 (函数模板)
std::get(std::array) | 访问 `array` 的一个元素 (函数模板)