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_extentand 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);
}