Skip to content

Span

Span

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.

1
2
add_executable(span span.cpp)
target_compile_features(span PRIVATE cxx_std_20)

1
#include <span>

1
2
3
4
5
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);
}

1
2
3
4
5
6
template<class T, std::size_t N, std::size_t M>
[[nodiscard]]
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());
}

1
2
3
4
5
6
7
template<class T, std::size_t N, std::size_t M>
[[nodiscard]]
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());
}

1
2
3
4
5
6
template<class T, std::size_t N, std::size_t M>
[[nodiscard]]
constexpr bool contains(std::span<T, N> span, std::span<T, M> sub) {
    return std::search(span.begin(), span.end(), sub.begin(), sub.end())
           != span.end();
}

1
2
constexpr int a[]{0, 1, 2, 3, 4, 5, 6, 7, 8};
constexpr int b[]{8, 7, 6};

1
2
3
4
5
6
7
for (std::size_t offset{};; ++offset) {
    constexpr std::size_t width{6};
    auto s = slide(std::span{a}, offset, width);
    if (s.empty())
        break;
    print(s);
}

1
2
3
4
5
6
7
8
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}));

Share Snippets