Gaia-ECS v1.0.0
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 <initializer_list>
13#include <tuple>
14#include <type_traits>
15
16#include "gaia/core/iterator.h"
17#include "gaia/core/utility.h"
18
19namespace gaia {
20 namespace core {
22 using span_difference_type = size_t;
24 using span_size_type = size_t;
25 } // namespace core
26
27 namespace cnt {
28 template <typename T, uint32_t N>
29 class sarr;
30 template <typename T, uint32_t N>
31 using sarray = cnt::sarr<T, N>;
32 } // namespace cnt
33
34 namespace core {
36 inline constexpr span_size_type DynamicSpanExtent = (span_size_type)-1;
37
41 template <typename T, span_size_type Extent = DynamicSpanExtent>
42 class span;
43
45 namespace detail {
46 template <typename T, span_size_type Extent>
47 struct span_storage {
48 constexpr span_storage() noexcept = default;
49 constexpr span_storage(const span_storage&) noexcept = default;
50 constexpr span_storage(span_storage&&) noexcept = default;
51 constexpr span_storage& operator=(const span_storage&) noexcept = default;
52 constexpr span_storage& operator=(span_storage&&) noexcept = default;
53 constexpr span_storage(T* ptr_, span_size_type /*unused*/) noexcept: beg(ptr_), end(ptr_ + Extent) {}
54 ~span_storage() noexcept = default;
55
56 T* beg = nullptr;
57 T* end = nullptr;
58 static constexpr span_size_type size = Extent;
59 };
60
61 template <typename T>
62 struct span_storage<T, DynamicSpanExtent> {
63 constexpr span_storage() noexcept = default;
64 constexpr span_storage(const span_storage&) noexcept = default;
65 constexpr span_storage(span_storage&&) noexcept = default;
66 constexpr span_storage& operator=(const span_storage&) noexcept = default;
67 constexpr span_storage& operator=(span_storage&&) noexcept = default;
68 constexpr span_storage(T* ptr_, span_size_type size_) noexcept: beg(ptr_), end(ptr_ + size_) {}
69 ~span_storage() noexcept = default;
70
71 T* beg = nullptr;
72 T* end = nullptr;
73 };
74
75 template <typename>
76 struct is_span: std::false_type {};
77
78 template <typename T, span_size_type S>
79 struct is_span<span<T, S>>: std::true_type {};
80
81 template <typename>
82 struct is_std_array: std::false_type {};
83
84 template <typename T, auto N>
85 struct is_std_array<gaia::cnt::sarray<T, N>>: std::true_type {};
86
87 template <typename C, typename U = raw_t<C>>
88 struct is_container {
89 static constexpr bool value =
90 !is_span<U>::value && !is_std_array<U>::value && !std::is_array<U>::value && has_data_size<C>::value;
91 };
92
93 template <typename, typename, typename = void>
94 struct is_container_element_kind_compatible: std::false_type {};
95
96 template <typename T, typename E>
97 struct is_container_element_kind_compatible<
98 T, E,
99 typename std::enable_if<
100 !std::is_same<typename std::remove_cv<decltype(detail::data(std::declval<T>()))>::type, void>::value &&
101 std::is_convertible<
102 typename std::remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
103 E (*)[]>::value>::type>: std::true_type {};
104 } // namespace detail
106
110 template <typename T, span_size_type Extent>
111 class span {
112 static_assert(
113 std::is_object<T>::value, "A span's T must be an object type (not a "
114 "reference type or void)");
115 static_assert(
116 detail::is_complete<T>::value, "A span's T must be a complete type (not a forward "
117 "declaration)");
118 static_assert(!std::is_abstract<T>::value, "A span's T cannot be an abstract class type");
119
120 using m_datatype = detail::span_storage<T, Extent>;
121
122 public:
124 using element_kind = T;
126 using value_type = typename std::remove_cv<T>::type;
128 using size_type = span_size_type;
130 using difference_type = span_difference_type;
139
146
148 static constexpr size_type extent = Extent;
149
150 private:
151 m_datatype m_data{};
152
153 public:
156 template <span_size_type E = Extent, typename std::enable_if<(E == DynamicSpanExtent || E <= 0), int>::type = 0>
157 constexpr span() noexcept {}
158
161 template <
162 typename U,
163 typename std::enable_if<std::is_convertible<U (*)[], element_kind (*)[]>::value, int>::type = 0>
164 span(std::initializer_list<U>) = delete;
165
169 constexpr span(pointer ptr, size_type count): m_data(ptr, count) {
170 GAIA_ASSERT(extent == DynamicSpanExtent || extent == count);
171 }
172
176 constexpr span(pointer begin, pointer end): m_data(begin, end - begin) {
177 GAIA_ASSERT(extent == DynamicSpanExtent || ((uintptr_t)(end - begin) == (uintptr_t)extent));
178 }
179
184 template <
185 span_size_type N, span_size_type E = Extent,
186 typename std::enable_if<
187 (E == DynamicSpanExtent || N == E) &&
188 detail::is_container_element_kind_compatible<element_kind (&)[N], T>::value,
189 int>::type = 0>
190 constexpr span(element_kind (&arr)[N]) noexcept: m_data(arr, N) {}
191
196 template <
197 typename Container, span_size_type E = Extent,
198 typename std::enable_if<
199 E == DynamicSpanExtent && detail::is_container<Container>::value &&
200 detail::is_container_element_kind_compatible<Container&, T>::value,
201 int>::type = 0>
202 constexpr span(Container& cont): m_data(detail::data(cont), detail::size(cont)) {}
203
208 template <
209 typename Container, span_size_type E = Extent,
210 typename std::enable_if<
211 E == DynamicSpanExtent && detail::is_container<Container>::value &&
212 detail::is_container_element_kind_compatible<const Container&, T>::value,
213 int>::type = 0>
214 constexpr span(const Container& cont): m_data(detail::data(cont), detail::size(cont)) {}
215
216 constexpr span(const span&) noexcept = default;
217 constexpr span& operator=(const span&) noexcept = default;
218
223 template <
224 typename T2, span_size_type Extent2,
225 typename std::enable_if<
226 (Extent == DynamicSpanExtent || Extent2 == DynamicSpanExtent || Extent == Extent2) &&
227 std::is_convertible<T2 (*)[], T (*)[]>::value,
228 int>::type = 0>
229 constexpr span(const span<T2, Extent2>& other) noexcept: m_data(other.data(), other.size()) {}
230
231 ~span() noexcept = default;
232
235 GAIA_NODISCARD constexpr pointer data() const noexcept {
236 return m_data.beg;
237 }
238
241 GAIA_NODISCARD constexpr size_type size() const noexcept {
242 return size_type(m_data.end - m_data.beg);
243 }
244
247 GAIA_NODISCARD constexpr bool empty() const noexcept {
248 return m_data.beg == m_data.end;
249 }
250
254 GAIA_NODISCARD constexpr reference operator[](size_type index) const {
255 GAIA_ASSERT((uintptr_t)m_data.beg + index < (uintptr_t)m_data.end);
256 return *(m_data.beg + index);
257 }
258
261 GAIA_NODISCARD constexpr iterator begin() noexcept {
262 return {m_data.beg};
263 }
264
267 GAIA_NODISCARD constexpr iterator begin() const noexcept {
268 return {m_data.beg};
269 }
270
273 GAIA_NODISCARD constexpr const_iterator cbegin() const noexcept {
274 return {m_data.beg};
275 }
276
279 GAIA_NODISCARD constexpr iterator end() noexcept {
280 return {m_data.end};
281 }
282
285 GAIA_NODISCARD constexpr const_iterator end() const noexcept {
286 return {m_data.end};
287 }
288
291 GAIA_NODISCARD constexpr const_iterator cend() const noexcept {
292 return {m_data.end};
293 }
294
298 template <span_size_type Count>
299 GAIA_NODISCARD constexpr span<element_kind, Count> first() const {
300 GAIA_ASSERT(Count <= size());
301 return {m_data.beg, Count};
302 }
303
307 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent> first(size_type count) const {
308 GAIA_ASSERT(count <= size());
309 return {m_data.beg, count};
310 }
311
315 template <span_size_type Count>
316 GAIA_NODISCARD constexpr span<element_kind, Count> last() const {
317 GAIA_ASSERT(Count <= size());
318 return {m_data.beg + (size() - Count), Count};
319 }
320
324 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent> last(size_type count) const {
325 GAIA_ASSERT(count <= size());
326 return {m_data.beg + (size() - count), count};
327 }
328
331 GAIA_NODISCARD constexpr reference front() const {
332 GAIA_ASSERT(!empty());
333 return *m_data.beg;
334 }
335
338 GAIA_NODISCARD constexpr reference back() const {
339 GAIA_ASSERT(!empty());
340 return *(m_data.beg + (size() - 1));
341 }
342
346 template <span_size_type Offset, span_size_type Count = DynamicSpanExtent>
348 T, Count != DynamicSpanExtent ? Count : (Extent != DynamicSpanExtent ? Extent - Offset : DynamicSpanExtent)>;
349
354 template <span_size_type Offset, span_size_type Count = DynamicSpanExtent>
355 GAIA_NODISCARD constexpr subspan_return_t<Offset, Count> subspan() const {
356 GAIA_ASSERT(Offset <= size() && (Count == DynamicSpanExtent || Offset + Count <= size()));
357 return {m_data.beg + Offset, Count != DynamicSpanExtent ? Count : size() - Offset};
358 }
359
364 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent>
365 subspan(size_type offset, size_type count = DynamicSpanExtent) const {
366 GAIA_ASSERT(offset <= size() && (count == DynamicSpanExtent || offset + count <= size()));
367 return {m_data.beg + offset, count != DynamicSpanExtent ? count : size() - offset};
368 }
369 };
370
375 template <typename T, size_t N>
376 span(T (&arr)[N]) -> span<T, N>;
377
382 template <typename T, size_t N>
383 span(gaia::cnt::sarray<T, N>& arr) -> span<T, N>;
384
389 template <typename T, size_t N>
390 span(const gaia::cnt::sarray<T, N>& arr) -> span<const T, N>;
391
395 template <typename Container>
396 span(Container& cont)
397 -> span<typename std::remove_reference<decltype(*detail::data(std::declval<Container&>()))>::type>;
398
402 template <typename Container>
403 span(const Container& cont) -> span<const typename Container::value_type>;
404
411 template <span_size_type N, typename E, span_size_type S>
412 constexpr auto get(span<E, S> s) -> decltype(s[N]) {
413 return s[N];
414 }
415 } // namespace core
416} // namespace gaia
417
419namespace std {
420 template <typename T, size_t Extent>
421 struct tuple_size<gaia::core::span<T, Extent>>: public integral_constant<size_t, Extent> {};
422
423 template <typename T>
424 struct tuple_size<gaia::core::span<T, gaia::core::DynamicSpanExtent>>; // not defined
425
426 template <size_t I, typename T, size_t Extent>
427 struct tuple_element<I, gaia::core::span<T, Extent>> {
428 static_assert(Extent != gaia::core::DynamicSpanExtent && I < Extent, "");
429 using type = T;
430 };
431} // end namespace std
Array of elements of type.
Definition darray_ext_impl.h:31
Non-owning view over a contiguous sequence of objects.
Definition span_impl.h:111
typename std::remove_cv< T >::type value_type
Element type without const qualification.
Definition span_impl.h:126
constexpr span(const Container &cont)
Constructs a dynamic-extent view over a compatible const container.
Definition span_impl.h:214
GAIA_NODISCARD constexpr iterator begin() noexcept
Returns an iterator to the first element.
Definition span_impl.h:261
constexpr span(element_kind(&arr)[N]) noexcept
Constructs a view over a compatible built-in array.
Definition span_impl.h:190
element_kind * pointer
Pointer to an element.
Definition span_impl.h:132
GAIA_NODISCARD constexpr reference front() const
Returns the first element.
Definition span_impl.h:331
GAIA_NODISCARD constexpr reference back() const
Returns the final element.
Definition span_impl.h:338
const_pointer const_iterator
Const iterator type.
Definition span_impl.h:143
span_difference_type difference_type
Type used for iterator differences.
Definition span_impl.h:130
span_size_type size_type
Type used for element counts.
Definition span_impl.h:128
const element_kind * const_pointer
Pointer to a const element.
Definition span_impl.h:134
GAIA_NODISCARD constexpr span< element_kind, DynamicSpanExtent > subspan(size_type offset, size_type count=DynamicSpanExtent) const
Returns a dynamic-extent subspan.
Definition span_impl.h:365
GAIA_NODISCARD constexpr const_iterator cend() const noexcept
Returns a const iterator one past the final element.
Definition span_impl.h:291
constexpr span(const span< T2, Extent2 > &other) noexcept
Constructs a compatible span from another element type or extent.
Definition span_impl.h:229
GAIA_NODISCARD constexpr iterator begin() const noexcept
Returns an iterator to the first element.
Definition span_impl.h:267
element_kind & reference
Reference to an element.
Definition span_impl.h:136
pointer iterator
Mutable iterator type.
Definition span_impl.h:141
GAIA_NODISCARD constexpr const_iterator end() const noexcept
Returns a const iterator one past the final element.
Definition span_impl.h:285
constexpr span(pointer ptr, size_type count)
Constructs a view over count elements starting at ptr.
Definition span_impl.h:169
GAIA_NODISCARD constexpr reference operator[](size_type index) const
Returns the element at index.
Definition span_impl.h:254
GAIA_NODISCARD constexpr span< element_kind, DynamicSpanExtent > first(size_type count) const
Returns a dynamic-extent view over the first count elements.
Definition span_impl.h:307
const element_kind & const_reference
Reference to a const element.
Definition span_impl.h:138
GAIA_NODISCARD constexpr bool empty() const noexcept
Checks whether the view is empty.
Definition span_impl.h:247
GAIA_NODISCARD constexpr subspan_return_t< Offset, Count > subspan() const
Returns a subspan selected with compile-time offset and count.
Definition span_impl.h:355
GAIA_NODISCARD constexpr size_type size() const noexcept
Returns the number of elements in the view.
Definition span_impl.h:241
GAIA_NODISCARD constexpr span< element_kind, Count > first() const
Returns the first Count elements with a compile-time extent.
Definition span_impl.h:299
T element_kind
Element type, including const qualification.
Definition span_impl.h:124
GAIA_NODISCARD constexpr iterator end() noexcept
Returns an iterator one past the final element.
Definition span_impl.h:279
GAIA_NODISCARD constexpr span< element_kind, DynamicSpanExtent > last(size_type count) const
Returns a dynamic-extent view over the last count elements.
Definition span_impl.h:324
constexpr span(Container &cont)
Constructs a dynamic-extent view over a compatible mutable container.
Definition span_impl.h:202
GAIA_NODISCARD constexpr const_iterator cbegin() const noexcept
Returns a const iterator to the first element.
Definition span_impl.h:273
constexpr span(pointer begin, pointer end)
Constructs a view over the half-open range [begin, end).
Definition span_impl.h:176
GAIA_NODISCARD constexpr span< element_kind, Count > last() const
Returns the last Count elements with a compile-time extent.
Definition span_impl.h:316
span(std::initializer_list< U >)=delete
Rejects temporary initializer-list storage because its backing array expires at the end of the full e...