userver: userver/utils/impl/span.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
span.hpp
1#pragma once
2
3#include <cstddef>
4#include <iterator>
5#include <type_traits>
6
7#include <userver/utils/assert.hpp>
8
9USERVER_NAMESPACE_BEGIN
10
11namespace utils::impl {
12
13template <typename T>
14class Span final {
15 public:
16 using iterator = T*;
17 using const_iterator = T*; // Span has pointer semantics
18
19 constexpr Span() : Span(nullptr, nullptr) {}
20
21 constexpr Span(T* begin, T* end) noexcept : begin_(begin), end_(end) {
22 UASSERT((begin != nullptr && end != nullptr && begin <= end) ||
23 (begin == nullptr && end == nullptr));
24 }
25
26 template <
27 typename Container,
28 typename = std::enable_if_t<
29 // Container is a range
30 !std::is_same_v<decltype(*std::begin(std::declval<Container&&>())),
31 void> &&
32 // Copy and move constructor fix
33 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<Container>>,
34 Span>>>
35 constexpr /*implicit*/ Span(Container&& cont) noexcept
36 : Span(std::data(cont), std::data(cont) + std::size(cont)) {}
37
38 constexpr T* begin() const noexcept { return begin_; }
39 constexpr T* end() const noexcept { return end_; }
40
41 constexpr T* data() const noexcept { return begin_; }
42 constexpr std::size_t size() const noexcept { return end_ - begin_; }
43
44 constexpr Span<T> first(std::size_t count) const noexcept {
45 UASSERT(count <= size());
46 return Span{begin_, begin_ + count};
47 }
48
49 constexpr Span<T> last(std::size_t count) const noexcept {
50 UASSERT(count <= size());
51 return Span{end_ - count, end_};
52 }
53
54 constexpr Span<T> subspan(std::size_t offset, std::size_t count) const
55 noexcept {
56 UASSERT(offset + count <= size());
57 return Span{begin_ + offset, begin_ + offset + count};
58 }
59
60 constexpr T& operator[](std::size_t index) const noexcept {
61 UASSERT(index < size());
62 return begin_[index];
63 }
64
65 private:
66 T* begin_;
67 T* end_;
68};
69
70template <typename Container>
71Span(Container&& cont)
72 -> Span<std::remove_reference_t<decltype(*std::begin(cont))>>;
73
74} // namespace utils::impl
75
76USERVER_NAMESPACE_END