| Home | Libraries | People | FAQ | More

## span

### Authors

- Glen Fernandes

### Overview

This header <boost/core/span.hpp> provides class template `span`, which is a view over a sequence of objects. It implements the C++20 standard library `std::span` facility. This implementation supports C++11 and higher.

In addition to referencing the sequence of objects, the span knows the count of objects. There are two kinds of spans:

- Dynamic size (`span<T>` or `span<T, dynamic_extent>`)
- Static size (`span<T, N>`)

Dynamic size spans have a count that can be a value known at run time. Static size spans have a count that must be known at compile time.

### Examples

The following snippet shows a function to compute a SHA1 hash whose parameters and return type use spans.

    auto sha1(boost::span<const unsigned char> input,
        boost::span<unsigned char, SHA_DIGEST_LENGTH> output)
    {
        SHA_CTX context;
        SHA1_Init(&context);
        SHA1_Update(&context, input.data(), input.size());
        SHA1_Final(output.data(), &context);
        return output;
    }

### Reference

    namespace boost {

    constexpr std::size_t dynamic_extent = -1;

    template<class T, std::size_t E = dynamic_extent>
    class span {
    public:
        typedef T element_type;
        typedef std::remove_cv_t<T> value_type;
        typedef std::size_t size_type;
        typedef std::ptrdiff_t difference_type;
        typedef T* pointer;
        typedef const T* const_pointer;
        typedef T& reference;
        typedef const T& const_reference;
        typedef T* iterator;
        typedef const T* const_iterator;
        typedef std::reverse_iterator<T*> reverse_iterator;
        typedef std::reverse_iterator<const T*> const_reverse_iterator;

        static constexpr std::size_t extent = E;

        constexpr span() noexcept;

        explicit(E != dynamic_extent)
        template<class I>
        constexpr span(I* f, size_type c);

        explicit(E != dynamic_extent)
        template<class I, class L>
        constexpr span(I* f, L* l);

        template<std::size_t N>
        constexpr span(type_identity_t<T> (&a)[N]);

        template<class U, std::size_t N>
        constexpr span(std::array<U, N>& a) noexcept;

        template<class U, std::size_t N>
        constexpr span(const std::array<U, N>& a) noexcept;

        explicit(E != dynamic_extent)
        template<class R>
        constexpr span(R&& r);

        explicit(E != dynamic_extent && N == dynamic_extent)
        template<class U, std::size_t N>
        constexpr span(const span<U, N>& s) noexcept;

        template<std::size_t C>
        constexpr span<T, C> first() const;

        template<std::size_t C>
        constexpr span<T, C> last() const;

        template<std::size_t O, std::size_t C = dynamic_extent>
        constexpr span<T, see below> subspan() const;

        constexpr span<T, dynamic_extent> first(size_type c) const;
        constexpr span<T, dynamic_extent> last(size_type c) const;

        constexpr span<T, dynamic_extent> subspan(size_type o,
            size_type c = dynamic_extent) const;

        constexpr size_type size() const noexcept;
        constexpr size_type size_bytes() const noexcept;
        constexpr bool empty() const noexcept;

        constexpr reference operator[](size_type i) const;
        constexpr reference front() const;
        constexpr reference back() const;
        constexpr pointer data() const noexcept;

        constexpr iterator begin() const noexcept;
        constexpr iterator end() const noexcept;
        constexpr reverse_iterator rbegin() const noexcept;
        constexpr reverse_iterator rend() const noexcept;
        constexpr const_iterator cbegin() const noexcept;
        constexpr const_iterator cend() const noexcept;
        constexpr const_reverse_iterator crbegin() const noexcept;
        constexpr const_reverse_iterator crend() const noexcept;
    };

    template<class I, class L>
    span(I*, L) -> span<I>;

    template<class T, std::size_t N>
    span(T(&)[N]) -> span<T, N>;

    template<class T, std::size_t N>
    span(std::array<T, N>&) -> span<T, N>;

    template<class T, std::size_t N>
    span(const std::array<T, N>&) -> span<const T, N>;

    template<class R>
    span(R&&) -> span<remove_pointer_t<iterator_t<R> > >;

    template<class T, std::size_t E>
    span<const std::byte, E == dynamic_extent ? dynamic_extent : sizeof(T) * E>
    as_bytes(span<T, E> s) noexcept;

    template<class T, std::size_t E>
    span<std::byte, E == dynamic_extent ? dynamic_extent : sizeof(T) * E>
    as_writable_bytes(span<T, E> s) noexcept;

    } /* boost */

#### Constructors

`constexpr span() noexcept;`

  Constraints

    `E == dynamic_extent || E == 0` is `true`.

  Postconditions

    `size() == 0 && data() == nullptr`.

`explicit(E != dynamic_extent) template<class I> constexpr span(I* f, size_type c);`

  Constraints

    `is_convertible_v<I(*)[], T(*)[]>` is `true`.

  Preconditions
    - `[f, f + c)` is a valid range.
    - If `E` is not equal to `dynamic_extent`, then `c` is equal to `E`.
  Effects
    Constructs a `span` with data `f` and size `c`.
  Throws

    Nothing.

`explicit(E != dynamic_extent) template<class I, class L> constexpr span(I* f, L* l);`

  Constraints

    `is_convertible_v<I(*)[], T(*)[]>` is `true`.

  Preconditions
    - If `E` is not equal to `dynamic_extent`, then `l - f` is equal to `E`.
    - `[f, l)` is a valid range.
  Effects
    Constructs a `span` with data `f` and size `l - f`.
  Throws

    Nothing.

`template<std::size_t N> constexpr span(type_identity_t<T> (&a)[N]);`

  Constraints

    `E == dynamic_extent || E == N` is `true`.

  Effects

    Constructs a `span` that is a view over the supplied array.

  Postconditions

    `size() == N && data() == &a[0]` is `true`.

`template<class U, std::size_t N> constexpr span(std::array<U, N>& a) noexcept;`

  Constraints
    - `E == dynamic_extent || E == N` is `true`, and
    - `U(*)[]` is convertible to `T(*)[]`.
  Effects
    Constructs a `span` that is a view over the supplied array.
  Postconditions

    `size() == N && data() == a.data()` is `true`.

`template<class U, std::size_t N> constexpr span(const std::array<U, N>& a) noexcept;`

  Constraints
    - `E == dynamic_extent || E == N` is `true`, and
    - `U(*)[]` is convertible to `T(*)[]`.
  Effects
    Constructs a `span` that is a view over the supplied array.
  Postconditions

    `size() == N && data() == a.data()` is `true`.

`explicit(E != dynamic_extent) template<class R> constexpr span(R&& r);`

  Constraints
    - `is_lvalue_reference_v<R> || is_const_v<T>` is `true`
    - `remove_cvref_t<R>` is not a specialization of `span`,
    - `remove_cvref_t<R>` is not a specialization of `array`,
    - `is_array_v<remove_cvref_t<R>>` is `false`,
    - `data(r)` is well-formed and `is_convertible_v<remove_pointer_t<iterator_t<R> >(*)[], T(*)[]>` is `true`, and
    - `r.size()` is well-formed and `is_convertible_v<decltype(declval<R&>().size()), size_t>` is `true`.
  Effects
    Constructs a `span` with data `data(r)` and size `r.size()`.
  Throws

    What and when data(r) and r.size() throw.

`explicit(E != dynamic_extent && N == dynamic_extent) template<class U, std::size_t N> constexpr span(const span<U, N>& s) noexcept;`

  Constraints
    - `E == dynamic_extent || N == dynamic_extent || E == N` is `true`, and
    - `is_convertible_v<U(*)[], T(*)[]>` is `true`.
  Preconditions
    If `E` is not equal to `dynamic_extent`, then `s.size()` is equal to `E`.
  Effects

    Constructs a `span` that is a view over the range `[s.data(), s.data() + s.size())`.

  Postconditions

    `size() == s.size() && data() == s.data()`.

#### Subviews

`template<std::size_t C> constexpr span<T, C> first() const;`

  Mandates

    `C <= E` is `true`.

  Preconditions

    `C <= size()` is `true`.

  Effects

    Equivalent to `return R{data(), C};` where `R` is the return type.

`template<std::size_t C> constexpr span<T, C> last() const;`

  Mandates

    `C <= E` is `true`.

  Preconditions

    `C <= size()` is `true`.

  Effects

    Equivalent to `return R{data() + (size() - C), C};` where `R` is the return type.

`template<std::size_t O, std::size_t C = dynamic_extent> constexpr span<T, see below> subspan() const;`

  Mandates

    `O <= E && (C == dynamic_extent || C <= E - O)` is `true`.

  Preconditions

    `O <= size() && (C == dynamic_extent || C <= size() - O)` is `true`.

  Effects

    Equivalent to `return span<T, see below>(data() + O, C != dynamic_extent ? C : size() - O);`.

  Remarks

    The second template argument of the returned span type is: `C != dynamic_extent ? C : (E != dynamic_extent ? E - O : dynamic_extent)`

`constexpr span<T, dynamic_extent> first(size_type c) const;`

  Preconditions

    `c <= size()` is `true`.

  Effects

    Equivalent to: `return {data(), c};`

`constexpr span<T, dynamic_extent> last(size_type c) const;`

  Preconditions

    `c <= size()` is `true`.

  Effects

    Equivalent to: `return {data() + (size() - c), c};`

`constexpr span<T, dynamic_extent> subspan(size_type o, size_type c = dynamic_extent) const;`

  Preconditions

    `o <= size() && (c == dynamic_extent || o + c <= size())` is `true`.

  Effects

    Equivalent to: `return {data() + o, c == dynamic_extent ? size() - o : c};`

#### Observers

`constexpr size_type size() const noexcept;`

  Returns

    The number of elements in the span.

`constexpr size_type size_bytes() const noexcept;`

  Effects

    Equivalent to: `return size() * sizeof(T);`

`constexpr bool empty() const noexcept;`

  Effects

    Equivalent to: `return size() == 0;`

#### Element access

`constexpr reference operator[](size_type i) const;`

  Preconditions

    `i < size()` is `true`.

  Effects

    Equivalent to: `return *(data() + i);`

`constexpr reference front() const;`

  Preconditions

    `empty()` is `false`.

  Effects

    Equivalent to: `return *data();`

`constexpr reference back() const;`

  Preconditions

    `empty()` is `false`.

  Effects

    Equivalent to: `return *(data() + (size() - 1);`

`constexpr pointer data() const noexcept;`

  Returns

    A pointer to the first element in the span.

#### Iterator support

`constexpr iterator begin() const noexcept;`

  Returns

    A constant iterator referring to the first element in the span. If `empty()`, then it returns the same value as `cend()`.

`constexpr iterator end() const noexcept;`

  Returns

    A constant iterator which is the past-the-end value.

`constexpr reverse_iterator rbegin() const noexcept;`

  Effects

    Equivalent to: `return reverse_iterator(end());`

`constexpr reverse_iterator rend() const noexcept;`

  Effects

    Equivalent to: `return reverse_iterator(begin());`

`constexpr const_iterator cbegin() const noexcept;`

  Returns

    A constant iterator referring to the first element in the span. If `empty()`, then it returns the same value as `cend()`.

`constexpr const_iterator cend() const noexcept;`

  Returns

    A constant iterator which is the past-the-end value.

`constexpr const_reverse_iterator crbegin() const noexcept;`

  Effects

    Equivalent to: `return const_reverse_iterator(cend());`

`constexpr const_reverse_iterator crend() const noexcept;`

  Effects

    Equivalent to: `return const_reverse_iterator(cbegin());`

#### Views of object representation

`template<class T, std::size_t E> span<const std::byte, E == dynamic_extent ? dynamic_extent : sizeof(T) * E> as_bytes(span<T, E> s) noexcept;`

  Effects

    Equivalent to: `return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};`.

`template<class T, std::size_t E> span<std::byte, E == dynamic_extent ? dynamic_extent : sizeof(T) * E> as_writable_bytes(span<T, E> s) noexcept;`

  Constraints

    `is_const_v<T>` is `false`.

  Effects

    Equivalent to: `return R{reinterpret_cast<byte*>(s.data()), s.size_bytes()};` where `R` is the return type.