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
- Offset is greater than Extent, or
- Count is not
std::dynamic_extent
and Count is greater than Extent - Offset.
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); }