Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
span_impl.h
1
2// Span-compatible interface for c++17 based on:
3// https://github.com/tcbrindle/span
4// Copyright Tristan Brindle 2018.
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file ../../LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
8
9#pragma once
10#include "gaia/config/config.h"
11
12#include <tuple>
13#include <type_traits>
14
15#include "gaia/core/iterator.h"
16#include "gaia/core/utility.h"
17
18namespace gaia {
19 namespace core {
20 using span_diff_type = size_t;
21 using span_size_type = size_t;
22 } // namespace core
23
24 namespace cnt {
25 template <typename T, uint32_t N>
26 class sarr;
27 template <typename T, uint32_t N>
28 using sarray = cnt::sarr<T, N>;
29 } // namespace cnt
30
31 namespace core {
32 inline constexpr span_size_type DynamicSpanExtent = (span_size_type)-1;
33
34 template <typename T, span_size_type Extent = DynamicSpanExtent>
35 class span;
36
37 namespace detail {
38 template <typename T, span_size_type Extent>
39 struct span_storage {
40 constexpr span_storage() noexcept = default;
41 constexpr span_storage(const span_storage&) noexcept = default;
42 constexpr span_storage(span_storage&&) noexcept = default;
43 constexpr span_storage& operator=(const span_storage&) noexcept = default;
44 constexpr span_storage& operator=(span_storage&&) noexcept = default;
45 constexpr span_storage(T* ptr_, span_size_type /*unused*/) noexcept: beg(ptr_), end(ptr_ + Extent) {}
46 ~span_storage() noexcept = default;
47
48 T* beg = nullptr;
49 T* end = nullptr;
50 static constexpr span_size_type size = Extent;
51 };
52
53 template <typename T>
54 struct span_storage<T, DynamicSpanExtent> {
55 constexpr span_storage() noexcept = default;
56 constexpr span_storage(const span_storage&) noexcept = default;
57 constexpr span_storage(span_storage&&) noexcept = default;
58 constexpr span_storage& operator=(const span_storage&) noexcept = default;
59 constexpr span_storage& operator=(span_storage&&) noexcept = default;
60 constexpr span_storage(T* ptr_, span_size_type size_) noexcept: beg(ptr_), end(ptr_ + size_) {}
61 ~span_storage() noexcept = default;
62
63 T* beg = nullptr;
64 T* end = nullptr;
65 };
66
67 template <typename>
68 struct is_span: std::false_type {};
69
70 template <typename T, span_size_type S>
71 struct is_span<span<T, S>>: std::true_type {};
72
73 template <typename>
74 struct is_std_array: std::false_type {};
75
76 template <typename T, auto N>
77 struct is_std_array<gaia::cnt::sarray<T, N>>: std::true_type {};
78
79 template <typename C, typename U = raw_t<C>>
80 struct is_container {
81 static constexpr bool value =
82 !is_span<U>::value && !is_std_array<U>::value && !std::is_array<U>::value && has_data_size<C>::value;
83 };
84
85 template <typename, typename, typename = void>
86 struct is_container_element_kind_compatible: std::false_type {};
87
88 template <typename T, typename E>
90 T, E,
91 typename std::enable_if<
92 !std::is_same<typename std::remove_cv<decltype(detail::data(std::declval<T>()))>::type, void>::value &&
93 std::is_convertible<
94 typename std::remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
95 E (*)[]>::value>::type>: std::true_type {};
96 } // namespace detail
97
98 template <typename T, span_size_type Extent>
99 class span {
100 static_assert(
101 std::is_object<T>::value, "A span's T must be an object type (not a "
102 "reference type or void)");
103 static_assert(
104 detail::is_complete<T>::value, "A span's T must be a complete type (not a forward "
105 "declaration)");
106 static_assert(!std::is_abstract<T>::value, "A span's T cannot be an abstract class type");
107
109
110 public:
111 using element_kind = T;
112 using value_type = typename std::remove_cv<T>::type;
113 using size_type = span_size_type;
114 using difference_type = span_diff_type;
115 using pointer = element_kind*;
116 using const_pointer = const element_kind*;
117 using reference = element_kind&;
118 using const_reference = const element_kind&;
119
120 using iterator = pointer;
121 using const_iterator = const_pointer;
123
124 static constexpr size_type extent = Extent;
125
126 private:
127 m_datatype m_data{};
128
129 public:
130 template <span_size_type E = Extent, typename std::enable_if<(E == DynamicSpanExtent || E <= 0), int>::type = 0>
131 constexpr span() noexcept {}
132
133 constexpr span(pointer ptr, size_type count): m_data(ptr, count) {
134 GAIA_ASSERT(extent == DynamicSpanExtent || extent == count);
135 }
136
137 constexpr span(pointer begin, pointer end): m_data(begin, end - begin) {
138 GAIA_ASSERT(extent == DynamicSpanExtent || ((uintptr_t)(end - begin) == (uintptr_t)extent));
139 }
140
141 template <
142 span_size_type N, span_size_type E = Extent,
143 typename std::enable_if<
144 (E == DynamicSpanExtent || N == E) &&
145 detail::is_container_element_kind_compatible<element_kind (&)[N], T>::value,
146 int>::type = 0>
147 constexpr span(element_kind (&arr)[N]) noexcept: m_data(arr, N) {}
148
149 template <
150 typename Container, span_size_type E = Extent,
151 typename std::enable_if<
152 E == DynamicSpanExtent && detail::is_container<Container>::value &&
154 int>::type = 0>
155 constexpr span(Container& cont): m_data(detail::data(cont), detail::size(cont)) {}
156
157 template <
158 typename Container, span_size_type E = Extent,
159 typename std::enable_if<
160 E == DynamicSpanExtent && detail::is_container<Container>::value &&
162 int>::type = 0>
163 constexpr span(const Container& cont): m_data(detail::data(cont), detail::size(cont)) {}
164
165 constexpr span(const span& other) noexcept = default;
166 constexpr span& operator=(const span& other) noexcept = default;
167
168 template <
169 typename T2, span_size_type Extent2,
170 typename std::enable_if<
171 (Extent == DynamicSpanExtent || Extent2 == DynamicSpanExtent || Extent == Extent2) &&
172 std::is_convertible<T2 (*)[], T (*)[]>::value,
173 int>::type = 0>
174 constexpr span(const span<T2, Extent2>& other) noexcept: m_data(other.data(), other.size()) {}
175
176 ~span() noexcept = default;
177
178 GAIA_NODISCARD constexpr pointer data() const noexcept {
179 return m_data.beg;
180 }
181
182 GAIA_NODISCARD constexpr size_type size() const noexcept {
183 return size_type(m_data.end - m_data.beg);
184 }
185
186 GAIA_NODISCARD constexpr bool empty() const noexcept {
187 return m_data.beg == m_data.end;
188 }
189
190 GAIA_NODISCARD constexpr reference operator[](size_type index) const {
191 GAIA_ASSERT((uintptr_t)m_data.beg + index < (uintptr_t)m_data.end);
192 return *(m_data.beg + index);
193 }
194
195 GAIA_NODISCARD constexpr iterator begin() noexcept {
196 return {m_data.beg};
197 }
198
199 GAIA_NODISCARD constexpr iterator begin() const noexcept {
200 return {m_data.beg};
201 }
202
203 GAIA_NODISCARD constexpr const_iterator cbegin() const noexcept {
204 return {m_data.beg};
205 }
206
207 GAIA_NODISCARD constexpr iterator end() noexcept {
208 return {m_data.end};
209 }
210
211 GAIA_NODISCARD constexpr const_iterator end() const noexcept {
212 return {m_data.end};
213 }
214
215 GAIA_NODISCARD constexpr const_iterator cend() const noexcept {
216 return {m_data.end};
217 }
218
219 template <span_size_type Count>
220 GAIA_NODISCARD constexpr span<element_kind, Count> first() const {
221 GAIA_ASSERT(Count <= size());
222 return {m_data.beg, Count};
223 }
224
225 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent> first(size_type count) const {
226 GAIA_ASSERT(count <= size());
227 return {m_data.beg, count};
228 }
229
230 template <span_size_type Count>
231 GAIA_NODISCARD constexpr span<element_kind, Count> last() const {
232 GAIA_ASSERT(Count <= size());
233 return {m_data.beg + (size() - Count), Count};
234 }
235
236 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent> last(size_type count) const {
237 GAIA_ASSERT(count <= size());
238 return {m_data.beg + (size() - count), count};
239 }
240
241 GAIA_NODISCARD constexpr reference front() const {
242 GAIA_ASSERT(!empty());
243 return *m_data.beg;
244 }
245
246 GAIA_NODISCARD constexpr reference back() const {
247 GAIA_ASSERT(!empty());
248 return *(m_data.beg + (size() - 1));
249 }
250
251 template <span_size_type Offset, span_size_type Count = DynamicSpanExtent>
252 using subspan_return_t = span<
253 T, Count != DynamicSpanExtent ? Count : (Extent != DynamicSpanExtent ? Extent - Offset : DynamicSpanExtent)>;
254
255 template <span_size_type Offset, span_size_type Count = DynamicSpanExtent>
256 GAIA_NODISCARD constexpr subspan_return_t<Offset, Count> subspan() const {
257 GAIA_ASSERT(Offset <= size() && (Count == DynamicSpanExtent || Offset + Count <= size()));
258 return {m_data.beg + Offset, Count != DynamicSpanExtent ? Count : size() - Offset};
259 }
260
261 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent>
262 subspan(size_type offset, size_type count = DynamicSpanExtent) const {
263 GAIA_ASSERT(offset <= size() && (count == DynamicSpanExtent || offset + count <= size()));
264 return {m_data.beg + offset, count != DynamicSpanExtent ? count : size() - offset};
265 }
266 };
267
268 template <typename T, size_t N>
269 span(T (&)[N]) -> span<T, N>;
270
271 template <typename T, size_t N>
273
274 template <typename T, size_t N>
276
277 template <typename Container>
279
280 template <typename Container>
282
283 template <span_size_type N, typename E, span_size_type S>
284 constexpr auto get(span<E, S> s) -> decltype(s[N]) {
285 return s[N];
286 }
287 } // namespace core
288} // namespace gaia
289
290namespace std {
291 template <typename T, size_t Extent>
292 struct tuple_size<gaia::core::span<T, Extent>>: public integral_constant<size_t, Extent> {};
293
294 template <typename T>
295 struct tuple_size<gaia::core::span<T, gaia::core::DynamicSpanExtent>>; // not defined
296
297 template <size_t I, typename T, size_t Extent>
298 struct tuple_element<I, gaia::core::span<T, Extent>> {
299 static_assert(Extent != gaia::core::DynamicSpanExtent && I < Extent, "");
300 using type = T;
301 };
302} // end namespace std
Array of elements of type.
Definition sarray_impl.h:26
Definition span_impl.h:99
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition utility.h:51
Definition span_impl.h:80
Definition span_impl.h:68
Definition span_impl.h:74
Definition span_impl.h:39
Definition utility.h:144