# `std::span` 的推导指引

< cpp‎ | container‎ | span

定义于头文件 `<span>` |  |
template <class It, class EndOrSize> span(It, EndOrSize) -> span<std::remove_reference_t<std::iter_reference_t<It>>>; | (1) |
template<class T, std::size_t N> span(T (&)[N]) -> span<T, N>; | (2) |
template<class T, std::size_t N> span(std::array<T, N>&) -> span<T, N>; | (3) |
template<class T, std::size_t N> span(const std::array<T, N>&) -> span<const T, N>; | (4) |
template<class R> span(R&&) -> span<std::remove_reference_t<std::ranges::range_reference_t<R>>>; | (5) |

为 `span` 提供下列推导指引。

(1) 允许从迭代器-哨位对推导元素类型。此重载仅若 `It` 满足 `contiguous_iterator` 才参与重载决议。

(2-4) 允许从内建数组与 std::array 推导静态长度。

(5) 允许从范围推导元素类型。此重载仅若 `R` 满足 `contiguous_range` 才参与重载决议。

### 示例

    #include <array>
    #include <cstddef>
    #include <iomanip>
    #include <iostream>
    #include <span>
    #include <string_view>
    #include <vector>

    void print(std::string_view rem = "", std::size_t size_of = 0, std::size_t extent = 0) {
        if (rem.empty()) {
            std::cout << "name │ sizeof │ extent\n─────┼────────┼────────\n";
            return;
        }
        std::cout << std::setw(4) << rem << " │ " << std::setw(6) << size_of << " │ ";
        if (extent == std::dynamic_extent)
            std::cout << "dynamic";
        else
            std::cout << extent;
        std::cout << '\n';
    }

    int main() {
        int a[] {1, 2, 3, 4, 5};

        print();
        std::span s1 {std::begin(a), std::end(a)}; // 指引 (1)
        print("s1", sizeof s1, s1.extent);

        std::span s2 {std::begin(a), 3}; // 指引 (1)
        print("s2", sizeof s2, s2.extent);

        std::span s3 {a}; // 指引 (2)
        print("s3", sizeof s3, s3.extent);

        std::span<int> s4 {a}; // 不使用指引，制作动态 span
        print("s4", sizeof s4, s4.extent);

        std::array arr {6, 7, 8};
        std::span s5 {arr}; // 指引 (3)
        print("s5", sizeof s5, s5.extent);
        s5[0] = 42; // OK, element_type is 'int'

        const std::array arr2 {9, 10, 11};
        std::span s6 {arr2}; // 指引 (4)
        print("s6", sizeof s6, s6.extent);
        // s6[0] = 42; // Error: element_type is 'const int'

        std::vector v {66, 69, 99};
        std::span s7 {v}; // 指引 (5)
        print("s7", sizeof s7, s7.extent);
    }

输出：

    name │ sizeof │ extent
    ─────┼────────┼────────
      s1 │     16 │ dynamic
      s2 │     16 │ dynamic
      s3 │      8 │ 5
      s4 │     16 │ dynamic
      s5 │      8 │ 3
      s6 │      8 │ 3
      s7 │     16 │ dynamic