Class std::span in C++

Defined in header <span> (since C++20)

template<
    class T,
    std::size_t Extent = std::dynamic_extent
> class span;

where Extent is the number of elements in the sequence, or std::dynamic_extent if dynamic.

The class template span describes an object that can refer to a contiguous sequence of objects with the first element of the sequence at position zero. A span can either have a static extent, in which case the number of elements in the sequence is known at compile-time and encoded in the type, or a dynamic extent.

For a span s, pointers, iterators, and references to elements of s are invalidated when an operation invalidates a pointer in the range [s.data(), s.data() + s.size()).

All requirements on the iterator types of a Container apply to the iterator type of span as well.

No Decay

When you invoke a function taking a C-array, decay occurs. The function takes the C- array via a pointer to its first element. The C-array to pointer conversion is error-prone because length information of the C-array is lost.

In contrast, a std::span knows its length.

Constructors

Up to ten, taking arguments of type iterator, std::array, range&&, initializer_list, span...

constexpr span() noexcept; // (1) 	(since C++20)

template< class It >
explicit(extent != std::dynamic_extent)
constexpr span( It first, size_type count ); // (2) 	(since C++20)

template< class It, class End >
explicit(extent != std::dynamic_extent)
constexpr span( It first, End last ); // (3) 	(since C++20)

template< std::size_t N >
constexpr span( std::type_identity_t<element_type> (&arr)[N] ) noexcept; // (4) 	(since C++20)

template< class U, std::size_t N >
constexpr span( std::array<U, N>& arr ) noexcept; // (5) 	(since C++20)

template< class U, std::size_t N >
constexpr span( const std::array<U, N>& arr ) noexcept; // (6) 	(since C++20)

template< class R >
explicit(extent != std::dynamic_extent)
constexpr span( R&& range ); // (7) 	(since C++20)

explicit(extent != std::dynamic_extent)
constexpr span( std::initializer_list<value_type> il ) noexcept; // (8) 	(since C++26)

template< class U, std::size_t N >
explicit(extent != std::dynamic_extent && N == std::dynamic_extent)
constexpr span( const std::span<U, N>& source ) noexcept; // (9) 	(since C++20)

constexpr span( const span& other ) noexcept = default; // (10) 	(since C++20)

(4) constructs a span that is a view over the array arr; the resulting span has size() == N and data() == std::data(arr)

Example

#include <array>
#include <iostream>
#include <span>
#include <vector>

void print_span(std::span<const int> s)
{
    for (int n : s)
        std::cout << n << ' ';
    std::cout << '\n';
}

int main()
{
    int c[]{1, 2, 3};
    print_span(c); // constructs from array

    std::array a{4, 5, 6};
    print_span(a); // constructs from std::array

    std::vector v{7, 8, 9};
    print_span(v); // constructs from std::vector

#if __cpp_lib_span_initializer_list
    print_span({0, 1, 2}); // constructs from initializer_list
#else
    print_span({{0, 1, 2}}); // ditto, a workaround
#endif
}

Member Types

Member type definition
element_type T
value_type std::remove_cv_t<T>
size_type std::size_t
difference_type std::ptrdiff_t
pointer T*
const_pointer const T*
reference T&
const_reference const T&
iterator implementation-defined LegacyRandomAccessIterator, ConstexprIterator, and contiguous_iterator whose value_type is value_type
const_iterator (since C++23) std::const_iterator<iterator>
reverse_iterator std::reverse_iterator<iterator>
const_reverse_iterator (since C++23) std::const_iterator<reverse_iterator>

std::span: Methods returning iterators

The customary lot: begin(), end(), cbegin(), crend() (C++23),

std::span: Element access

front() access the first element
back() access the last element
at() (C++26) access specified element with bounds checking
operator[] access specified element
data() direct access to the underlying contiguous storage

std::span: Observers

size() returns the number of elements
size_bytes() returns the size of the sequence in bytes
empty() checks if the sequence is empty

std::span: Subviews

first(N) obtains a subspan consisting of the first N elements of the sequence
last(N) obtains a subspan consisting of the last N elements of the sequence
subspan() obtains a subspan

Example

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <span>

template<class T, std::size_t N>
[[nodiscard]]
constexpr auto slide(std::span<T, N> s, std::size_t offset, std::size_t width)
{
    return s.subspan(offset, offset + width <= s.size() ? width : 0U);
}

template<class T, std::size_t N, std::size_t M>
constexpr bool starts_with(std::span<T, N> data, std::span<T, M> prefix)
{
    return data.size() >= prefix.size()
        && std::equal(prefix.begin(), prefix.end(), data.begin());
}

template<class T, std::size_t N, std::size_t M>
constexpr bool ends_with(std::span<T, N> data, std::span<T, M> suffix)
{
    return data.size() >= suffix.size()
        && std::equal(data.end() - suffix.size(), data.end(),
                      suffix.end() - suffix.size());
}

template<class T, std::size_t N, std::size_t M>
constexpr bool contains(std::span<T, N> span, std::span<T, M> sub)
{
    return std::ranges::search(span, sub).begin() != span.end();
}

void println(const auto& seq)
{
    for (const auto& elem : seq)
        std::cout << elem << ' ';
    std::cout << '\n';
}

int main()
{
    constexpr int a[]{0, 1, 2, 3, 4, 5, 6, 7, 8};
    constexpr int b[]{8, 7, 6};
    constexpr static std::size_t width{6};

    for (std::size_t offset{}; ; ++offset)
        if (auto s = slide(std::span{a}, offset, width); !s.empty())
            println(s);
        else
            break;

    static_assert(""
        && starts_with(std::span{a}, std::span{a, 4})
        && starts_with(std::span{a + 1, 4}, std::span{a + 1, 3})
        && !starts_with(std::span{a}, std::span{b})
        && !starts_with(std::span{a, 8}, std::span{a + 1, 3})
        && ends_with(std::span{a}, std::span{a + 6, 3})
        && !ends_with(std::span{a}, std::span{a + 6, 2})
        && contains(std::span{a}, std::span{a + 1, 4})
        && !contains(std::span{a, 8}, std::span{a, 9})
    );
}

std::span<T,Extent>::subspan (since C++20)

template< std::size_t Offset,
          std::size_t Count = std::dynamic_extent >
constexpr std::span<element_type, E /* see below */>
    subspan() const;
constexpr std::span<element_type, std::dynamic_extent>
    subspan( size_type Offset,
             size_type Count = std::dynamic_extent ) const;

Obtains a span that is a view over the Count elements of this span starting at offset Offset. If Count is std::dynamic_extent, the number of elements in the subspan is size() - offset (i.e., it ends at the end of *this).

The former prototype is ill-formed if

Example

#include <algorithm>
#include <cstdio>
#include <numeric>
#include <ranges>
#include <span>

void display(std::span<const char> abc)
{
    const auto columns{20U};
    const auto rows{abc.size() - columns + 1};

    for (auto offset{0U}; offset < rows; ++offset)
    {
        std::ranges::for_each(abc.subspan(offset, columns), std::putchar);
        std::putchar('\n');
    }
}

int main()
{
    char abc[26];
    std::iota(std::begin(abc), std::end(abc), 'A');
    display(abc);
}