userver: userver/utils/span.hpp Source File
Loading...
Searching...
No Matches
span.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/span.hpp
4/// @brief @copybrief utils::span
5
6#include <concepts>
7#include <cstddef>
8#include <iterator>
9#include <span>
10#include <type_traits>
11
12// TODO remove extra include
13#include <userver/utils/assert.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace utils {
18
19/// A polyfill for std::span with some of the newer features enabled.
20template <typename T>
21class span : public std::span<T> { // NOLINT(readability-identifier-naming)
22public:
23 // std::span gains this alias only in C++23.
24 using const_iterator = typename std::span<T>::iterator;
25
26 using std::span<T>::span;
27
28 constexpr explicit(false) span(std::span<T> s) noexcept : std::span<T>(s) {}
29
30 // Allows converting utils::span<U> to utils::span<T>, following std::span.
31 template <typename U>
32 requires std::is_convertible_v<U (*)[], T (*)[]>
33 constexpr explicit(false) span(span<U> other) noexcept : std::span<T>(other.data(), other.size()) {}
34
35 // std::span will only gain this constructor in C++29 or later.
36 constexpr explicit(false) span(std::initializer_list<std::remove_cv_t<T>> il) noexcept
37 requires std::is_const_v<T> && (!std::same_as<std::decay_t<T>, bool>)
38 : std::span<T>(il.begin(), il.end()) {}
39};
40
41template <typename It, typename EndOrSize>
42span(It, EndOrSize) -> span<std::remove_reference_t<decltype(*std::declval<It&>())>>;
43
44template <typename R>
45requires std::ranges::contiguous_range<R>
46span(R&&) -> span<std::remove_reference_t<decltype(*std::begin(std::declval<R&>()))>>;
47
48/// Reinterprets the elements of a span as bytes.
49template <typename T>
50span<const std::byte> as_bytes(span<T> s) noexcept { // NOLINT(readability-identifier-naming)
51 return span<const std::byte>{std::as_bytes(std::span<T>{s})};
52}
53
54/// Reinterprets the elements of a span as writable bytes.
55template <typename T>
56requires(!std::is_const_v<T>)
57span<std::byte> as_writable_bytes(span<T> s) noexcept { // NOLINT(readability-identifier-naming)
58 return span<std::byte>{std::as_writable_bytes(std::span<T>{s})};
59}
60
61} // namespace utils
62
63USERVER_NAMESPACE_END
64
65// std::span must implement std::ranges::enable_borrowed_range, so <span> will pull it in.
66template <typename T>
67inline constexpr bool std::ranges::enable_borrowed_range<USERVER_NAMESPACE::utils::span<T>> = true;
68
69// std::span must implement std::ranges::enable_view, so <span> will pull it in.
70template <typename T>
71inline constexpr bool std::ranges::enable_view<USERVER_NAMESPACE::utils::span<T>> = true;