userver: userver/utils/impl/span.hpp Source File
Loading...
Searching...
No Matches
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