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
5#pragma once
6
7#include <array>
8#include <cstddef>
9#include <iterator>
10#include <type_traits>
11#include <vector>
12
13#ifdef USE_STD_SPAN
14#include <span>
15#endif
16
17namespace utility_module
18{
19#ifdef USE_STD_SPAN
26 template <typename T, size_t Extent = std::dynamic_extent>
27 using span = std::span<T, Extent>;
28#else
38 template <typename T, size_t Extent = size_t(-1)>
39 class span
40 {
41 public:
42 // Member types
43 using element_type = T;
44 using value_type = std::remove_cv_t<T>;
45 using size_type = size_t;
46 using difference_type = ptrdiff_t;
47 using pointer = T*;
48 using const_pointer = const T*;
49 using reference = T&;
50 using const_reference = const T&;
53 using reverse_iterator = std::reverse_iterator<iterator>;
54 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
55
56 // Dynamic extent constant
57 static constexpr size_t dynamic_extent = size_t(-1);
58
59 // Constructors
60 constexpr span() noexcept : data_(nullptr), size_(0)
61 {
62 static_assert(Extent == dynamic_extent || Extent == 0,
63 "Default-constructed span must have dynamic extent or zero extent");
64 }
65
66 constexpr span(pointer ptr, size_type count) noexcept : data_(ptr), size_(count)
67 {
68 static_assert(Extent == dynamic_extent || Extent == count,
69 "Size mismatch in span construction");
70 }
71
72 constexpr span(pointer first, pointer last) noexcept : data_(first), size_(last - first)
73 {
74 static_assert(Extent == dynamic_extent || Extent == size_,
75 "Size mismatch in span construction");
76 }
77
78 // Constructor from std::array
79 template <size_t N>
80 constexpr span(std::array<value_type, N>& arr) noexcept
81 : data_(arr.data()), size_(N)
82 {
83 static_assert(Extent == dynamic_extent || Extent == N,
84 "Size mismatch in span construction from array");
85 }
86
87 template <size_t N>
88 constexpr span(const std::array<value_type, N>& arr) noexcept
89 : data_(arr.data()), size_(N)
90 {
91 static_assert(Extent == dynamic_extent || Extent == N,
92 "Size mismatch in span construction from const array");
93 }
94
95 // Constructor from std::vector
96 template <typename Allocator>
97 constexpr span(std::vector<value_type, Allocator>& vec) noexcept
98 : data_(vec.data()), size_(vec.size())
99 {
100 static_assert(Extent == dynamic_extent || Extent == 0,
101 "Non-dynamic extent not supported for std::vector constructor");
102 }
103
104 template <typename Allocator>
105 constexpr span(const std::vector<value_type, Allocator>& vec) noexcept
106 : data_(vec.data()), size_(vec.size())
107 {
108 static_assert(Extent == dynamic_extent || Extent == 0,
109 "Non-dynamic extent not supported for std::vector constructor");
110 }
111
112 // Constructors from C-style arrays
113 template <size_t N>
114 constexpr span(element_type (&arr)[N]) noexcept
115 : data_(arr), size_(N)
116 {
117 static_assert(Extent == dynamic_extent || Extent == N,
118 "Size mismatch in span construction from array");
119 }
120
121 // Assignment operators
122 constexpr span& operator=(const span& other) noexcept = default;
123
124 // Observer methods
125 [[nodiscard]] constexpr size_type size() const noexcept { return size_; }
126 [[nodiscard]] constexpr size_type size_bytes() const noexcept { return size_ * sizeof(element_type); }
127 [[nodiscard]] constexpr bool empty() const noexcept { return size_ == 0; }
128
129 // Element access
130 [[nodiscard]] constexpr reference operator[](size_type idx) const noexcept
131 {
132 return data_[idx];
133 }
134
135 [[nodiscard]] constexpr reference front() const noexcept
136 {
137 return data_[0];
138 }
139
140 [[nodiscard]] constexpr reference back() const noexcept
141 {
142 return data_[size_ - 1];
143 }
144
145 [[nodiscard]] constexpr pointer data() const noexcept { return data_; }
146
147 // Iterator support
148 [[nodiscard]] constexpr iterator begin() const noexcept { return data_; }
149 [[nodiscard]] constexpr iterator end() const noexcept { return data_ + size_; }
150 [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return data_; }
151 [[nodiscard]] constexpr const_iterator cend() const noexcept { return data_ + size_; }
152 [[nodiscard]] constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
153 [[nodiscard]] constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
154 [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
155 [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
156
157 // Subviews
158 template<size_t Count>
159 [[nodiscard]] constexpr span<element_type, Count> first() const noexcept
160 {
161 return span<element_type, Count>(data_, Count);
162 }
163
164 [[nodiscard]] constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept
165 {
167 }
168
169 template<size_t Count>
170 [[nodiscard]] constexpr span<element_type, Count> last() const noexcept
171 {
172 return span<element_type, Count>(data_ + (size_ - Count), Count);
173 }
174
175 [[nodiscard]] constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept
176 {
177 return span<element_type, dynamic_extent>(data_ + (size_ - count), count);
178 }
179
180 template<size_t Offset, size_t Count = dynamic_extent>
181 [[nodiscard]] constexpr auto subspan() const noexcept
182 {
183 constexpr size_t new_extent = Count != dynamic_extent ? Count :
184 (Extent != dynamic_extent ? Extent - Offset : dynamic_extent);
186 data_ + Offset,
187 Count != dynamic_extent ? Count : (size_ - Offset));
188 }
189
190 [[nodiscard]] constexpr span<element_type, dynamic_extent>
191 subspan(size_type offset, size_type count = dynamic_extent) const noexcept
192 {
193 size_type new_count = count == dynamic_extent ? size_ - offset : count;
194 return span<element_type, dynamic_extent>(data_ + offset, new_count);
195 }
196
197 private:
200 };
201
202 // Deduction guides for span
203 template <class T, size_t N>
204 span(T (&)[N]) -> span<T, N>;
205
206 template <class T, size_t N>
207 span(std::array<T, N>&) -> span<T, N>;
208
209 template <class T, size_t N>
210 span(const std::array<T, N>&) -> span<const T, N>;
211
212 template <class Container>
213 span(Container&) -> span<typename Container::value_type>;
214
215 template <class Container>
216 span(const Container&) -> span<const typename Container::value_type>;
217#endif
218} // 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:88
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:181
constexpr span(pointer first, pointer last) noexcept
Definition span.h:72
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:135
constexpr span< element_type, dynamic_extent > subspan(size_type offset, size_type count=dynamic_extent) const noexcept
Definition span.h:191
constexpr span< element_type, dynamic_extent > last(size_type count) const noexcept
Definition span.h:175
constexpr iterator begin() const noexcept
Definition span.h:148
constexpr span< element_type, Count > last() const noexcept
Definition span.h:170
constexpr bool empty() const noexcept
Definition span.h:127
constexpr pointer data() const noexcept
Definition span.h:145
constexpr const_iterator cbegin() const noexcept
Definition span.h:150
size_t size_type
Definition span.h:45
constexpr size_type size() const noexcept
Definition span.h:125
constexpr span(std::vector< value_type, Allocator > &vec) noexcept
Definition span.h:97
std::remove_cv_t< T > value_type
Definition span.h:44
constexpr const_iterator cend() const noexcept
Definition span.h:151
constexpr reverse_iterator rend() const noexcept
Definition span.h:153
constexpr const_reverse_iterator crbegin() const noexcept
Definition span.h:154
const T & const_reference
Definition span.h:50
constexpr reference operator[](size_type idx) const noexcept
Definition span.h:130
constexpr reverse_iterator rbegin() const noexcept
Definition span.h:152
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:164
constexpr const_reverse_iterator crend() const noexcept
Definition span.h:155
constexpr span(std::array< value_type, N > &arr) noexcept
Definition span.h:80
constexpr iterator end() const noexcept
Definition span.h:149
constexpr reference back() const noexcept
Definition span.h:140
constexpr span(const std::vector< value_type, Allocator > &vec) noexcept
Definition span.h:105
constexpr span() noexcept
Definition span.h:60
constexpr span(pointer ptr, size_type count) noexcept
Definition span.h:66
size_type size_
Definition span.h:199
constexpr span(element_type(&arr)[N]) noexcept
Definition span.h:114
constexpr span< element_type, Count > first() const noexcept
Definition span.h:159
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition span.h:54
constexpr size_type size_bytes() const noexcept
Definition span.h:126
span(T(&)[N]) -> span< T, N >