Thread System 0.3.1
High-performance C++20 thread pool with work stealing and DAG scheduling
Loading...
Searching...
No Matches
span.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
11#pragma once
12
13#include <array>
14#include <cstddef>
15#include <iterator>
16#include <type_traits>
17#include <vector>
18
19#ifdef USE_STD_SPAN
20#include <span>
21#endif
22
23namespace utility_module
24{
25#ifdef USE_STD_SPAN
32 template <typename T, size_t Extent = std::dynamic_extent>
33 using span = std::span<T, Extent>;
34#else
44 template <typename T, size_t Extent = size_t(-1)>
45 class span
46 {
47 public:
48 // Member types
49 using element_type = T;
50 using value_type = std::remove_cv_t<T>;
51 using size_type = size_t;
52 using difference_type = ptrdiff_t;
53 using pointer = T*;
54 using const_pointer = const T*;
55 using reference = T&;
56 using const_reference = const T&;
57 using iterator = pointer;
59 using reverse_iterator = std::reverse_iterator<iterator>;
60 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
61
62 // Dynamic extent constant
63 static constexpr size_t dynamic_extent = size_t(-1);
64
65 // Constructors
66 constexpr span() noexcept : data_(nullptr), size_(0)
67 {
68 static_assert(Extent == dynamic_extent || Extent == 0,
69 "Default-constructed span must have dynamic extent or zero extent");
70 }
71
72 constexpr span(pointer ptr, size_type count) noexcept : data_(ptr), size_(count)
73 {
74 static_assert(Extent == dynamic_extent || Extent == count,
75 "Size mismatch in span construction");
76 }
77
78 constexpr span(pointer first, pointer last) noexcept : data_(first), size_(last - first)
79 {
80 static_assert(Extent == dynamic_extent || Extent == size_,
81 "Size mismatch in span construction");
82 }
83
84 // Constructor from std::array
85 template <size_t N>
86 constexpr span(std::array<value_type, N>& arr) noexcept
87 : data_(arr.data()), size_(N)
88 {
89 static_assert(Extent == dynamic_extent || Extent == N,
90 "Size mismatch in span construction from array");
91 }
92
93 template <size_t N>
94 constexpr span(const std::array<value_type, N>& arr) noexcept
95 : data_(arr.data()), size_(N)
96 {
97 static_assert(Extent == dynamic_extent || Extent == N,
98 "Size mismatch in span construction from const array");
99 }
100
101 // Constructor from std::vector
102 template <typename Allocator>
103 constexpr span(std::vector<value_type, Allocator>& vec) noexcept
104 : data_(vec.data()), size_(vec.size())
105 {
106 static_assert(Extent == dynamic_extent || Extent == 0,
107 "Non-dynamic extent not supported for std::vector constructor");
108 }
109
110 template <typename Allocator>
111 constexpr span(const std::vector<value_type, Allocator>& vec) noexcept
112 : data_(vec.data()), size_(vec.size())
113 {
114 static_assert(Extent == dynamic_extent || Extent == 0,
115 "Non-dynamic extent not supported for std::vector constructor");
116 }
117
118 // Constructors from C-style arrays
119 template <size_t N>
120 constexpr span(element_type (&arr)[N]) noexcept
121 : data_(arr), size_(N)
122 {
123 static_assert(Extent == dynamic_extent || Extent == N,
124 "Size mismatch in span construction from array");
125 }
126
127 // Assignment operators
128 constexpr span& operator=(const span& other) noexcept = default;
129
130 // Observer methods
131 [[nodiscard]] constexpr size_type size() const noexcept { return size_; }
132 [[nodiscard]] constexpr size_type size_bytes() const noexcept { return size_ * sizeof(element_type); }
133 [[nodiscard]] constexpr bool empty() const noexcept { return size_ == 0; }
134
135 // Element access
136 [[nodiscard]] constexpr reference operator[](size_type idx) const noexcept
137 {
138 return data_[idx];
139 }
140
141 [[nodiscard]] constexpr reference front() const noexcept
142 {
143 return data_[0];
144 }
145
146 [[nodiscard]] constexpr reference back() const noexcept
147 {
148 return data_[size_ - 1];
149 }
150
151 [[nodiscard]] constexpr pointer data() const noexcept { return data_; }
152
153 // Iterator support
154 [[nodiscard]] constexpr iterator begin() const noexcept { return data_; }
155 [[nodiscard]] constexpr iterator end() const noexcept { return data_ + size_; }
156 [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return data_; }
157 [[nodiscard]] constexpr const_iterator cend() const noexcept { return data_ + size_; }
158 [[nodiscard]] constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
159 [[nodiscard]] constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
160 [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
161 [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
162
163 // Subviews
164 template<size_t Count>
165 [[nodiscard]] constexpr span<element_type, Count> first() const noexcept
166 {
167 return span<element_type, Count>(data_, Count);
168 }
169
170 [[nodiscard]] constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept
171 {
173 }
174
175 template<size_t Count>
176 [[nodiscard]] constexpr span<element_type, Count> last() const noexcept
177 {
178 return span<element_type, Count>(data_ + (size_ - Count), Count);
179 }
180
181 [[nodiscard]] constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept
182 {
183 return span<element_type, dynamic_extent>(data_ + (size_ - count), count);
184 }
185
186 template<size_t Offset, size_t Count = dynamic_extent>
187 [[nodiscard]] constexpr auto subspan() const noexcept
188 {
189 constexpr size_t new_extent = Count != dynamic_extent ? Count :
190 (Extent != dynamic_extent ? Extent - Offset : dynamic_extent);
192 data_ + Offset,
193 Count != dynamic_extent ? Count : (size_ - Offset));
194 }
195
196 [[nodiscard]] constexpr span<element_type, dynamic_extent>
197 subspan(size_type offset, size_type count = dynamic_extent) const noexcept
198 {
199 size_type new_count = count == dynamic_extent ? size_ - offset : count;
200 return span<element_type, dynamic_extent>(data_ + offset, new_count);
201 }
202
203 private:
204 pointer data_;
205 size_type size_;
206 };
207
208 // Deduction guides for span
209 template <class T, size_t N>
210 span(T (&)[N]) -> span<T, N>;
211
212 template <class T, size_t N>
213 span(std::array<T, N>&) -> span<T, N>;
214
215 template <class T, size_t N>
216 span(const std::array<T, N>&) -> span<const T, N>;
217
218 template <class Container>
219 span(Container&) -> span<typename Container::value_type>;
220
221 template <class Container>
222 span(const Container&) -> span<const typename Container::value_type>;
223#endif
224} // namespace utility_module
A fallback span implementation for C++17 and earlier compilers.
Definition span.h:46
constexpr span(const std::array< value_type, N > &arr) noexcept
Definition span.h:94
const_pointer const_iterator
Definition span.h:52
ptrdiff_t difference_type
Definition span.h:46
constexpr span & operator=(const span &other) noexcept=default
constexpr auto subspan() const noexcept
Definition span.h:187
constexpr span(pointer first, pointer last) noexcept
Definition span.h:78
const T * const_pointer
Definition span.h:48
static constexpr size_t dynamic_extent
Definition span.h:57
constexpr reference front() const noexcept
Definition span.h:141
constexpr span< element_type, dynamic_extent > subspan(size_type offset, size_type count=dynamic_extent) const noexcept
Definition span.h:197
constexpr span< element_type, dynamic_extent > last(size_type count) const noexcept
Definition span.h:181
constexpr iterator begin() const noexcept
Definition span.h:154
constexpr span< element_type, Count > last() const noexcept
Definition span.h:176
constexpr bool empty() const noexcept
Definition span.h:133
constexpr pointer data() const noexcept
Definition span.h:151
constexpr const_iterator cbegin() const noexcept
Definition span.h:156
size_t size_type
Definition span.h:45
constexpr size_type size() const noexcept
Definition span.h:131
constexpr span(std::vector< value_type, Allocator > &vec) noexcept
Definition span.h:103
std::remove_cv_t< T > value_type
Definition span.h:44
constexpr const_iterator cend() const noexcept
Definition span.h:157
constexpr reverse_iterator rend() const noexcept
Definition span.h:159
constexpr const_reverse_iterator crbegin() const noexcept
Definition span.h:160
const T & const_reference
Definition span.h:50
constexpr reference operator[](size_type idx) const noexcept
Definition span.h:136
constexpr reverse_iterator rbegin() const noexcept
Definition span.h:158
std::reverse_iterator< iterator > reverse_iterator
Definition span.h:53
pointer iterator
Definition span.h:51
constexpr span< element_type, dynamic_extent > first(size_type count) const noexcept
Definition span.h:170
constexpr const_reverse_iterator crend() const noexcept
Definition span.h:161
constexpr span(std::array< value_type, N > &arr) noexcept
Definition span.h:86
constexpr iterator end() const noexcept
Definition span.h:155
constexpr reference back() const noexcept
Definition span.h:146
constexpr span(const std::vector< value_type, Allocator > &vec) noexcept
Definition span.h:111
constexpr span() noexcept
Definition span.h:66
constexpr span(pointer ptr, size_type count) noexcept
Definition span.h:72
size_type size_
Definition span.h:199
constexpr span(element_type(&arr)[N]) noexcept
Definition span.h:120
constexpr span< element_type, Count > first() const noexcept
Definition span.h:165
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition span.h:54
constexpr size_type size_bytes() const noexcept
Definition span.h:132
span(T(&)[N]) -> span< T, N >