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 <tuple>
13#include <type_traits>
14
15#include "gaia/core/iterator.h"
16#include "gaia/core/utility.h"
17
18namespace gaia {
19 namespace core {
21 using span_diff_type = size_t;
23 using span_size_type = size_t;
24 } // namespace core
25
26 namespace cnt {
27 template <typename T, uint32_t N>
28 class sarr;
29 template <typename T, uint32_t N>
30 using sarray = cnt::sarr<T, N>;
31 } // namespace cnt
32
33 namespace core {
35 inline constexpr span_size_type DynamicSpanExtent = (span_size_type)-1;
36
40 template <typename T, span_size_type Extent = DynamicSpanExtent>
41 class span;
42
44 namespace detail {
45 template <typename T, span_size_type Extent>
46 struct span_storage {
47 constexpr span_storage() noexcept = default;
48 constexpr span_storage(const span_storage&) noexcept = default;
49 constexpr span_storage(span_storage&&) noexcept = default;
50 constexpr span_storage& operator=(const span_storage&) noexcept = default;
51 constexpr span_storage& operator=(span_storage&&) noexcept = default;
52 constexpr span_storage(T* ptr_, span_size_type /*unused*/) noexcept: beg(ptr_), end(ptr_ + Extent) {}
53 ~span_storage() noexcept = default;
54
55 T* beg = nullptr;
56 T* end = nullptr;
57 static constexpr span_size_type size = Extent;
58 };
59
60 template <typename T>
61 struct span_storage<T, DynamicSpanExtent> {
62 constexpr span_storage() noexcept = default;
63 constexpr span_storage(const span_storage&) noexcept = default;
64 constexpr span_storage(span_storage&&) noexcept = default;
65 constexpr span_storage& operator=(const span_storage&) noexcept = default;
66 constexpr span_storage& operator=(span_storage&&) noexcept = default;
67 constexpr span_storage(T* ptr_, span_size_type size_) noexcept: beg(ptr_), end(ptr_ + size_) {}
68 ~span_storage() noexcept = default;
69
70 T* beg = nullptr;
71 T* end = nullptr;
72 };
73
74 template <typename>
75 struct is_span: std::false_type {};
76
77 template <typename T, span_size_type S>
78 struct is_span<span<T, S>>: std::true_type {};
79
80 template <typename>
81 struct is_std_array: std::false_type {};
82
83 template <typename T, auto N>
84 struct is_std_array<gaia::cnt::sarray<T, N>>: std::true_type {};
85
86 template <typename C, typename U = raw_t<C>>
87 struct is_container {
88 static constexpr bool value =
89 !is_span<U>::value && !is_std_array<U>::value && !std::is_array<U>::value && has_data_size<C>::value;
90 };
91
92 template <typename, typename, typename = void>
93 struct is_container_element_kind_compatible: std::false_type {};
94
95 template <typename T, typename E>
96 struct is_container_element_kind_compatible<
97 T, E,
98 typename std::enable_if<
99 !std::is_same<typename std::remove_cv<decltype(detail::data(std::declval<T>()))>::type, void>::value &&
100 std::is_convertible<
101 typename std::remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
102 E (*)[]>::value>::type>: std::true_type {};
103 } // namespace detail
105
109 template <typename T, span_size_type Extent>
110 class span {
111 static_assert(
112 std::is_object<T>::value, "A span's T must be an object type (not a "
113 "reference type or void)");
114 static_assert(
115 detail::is_complete<T>::value, "A span's T must be a complete type (not a forward "
116 "declaration)");
117 static_assert(!std::is_abstract<T>::value, "A span's T cannot be an abstract class type");
118
119 using m_datatype = detail::span_storage<T, Extent>;
120
121 public:
123 using element_kind = T;
125 using value_type = typename std::remove_cv<T>::type;
127 using size_type = span_size_type;
129 using difference_type = span_diff_type;
138
145
147 static constexpr size_type extent = Extent;
148
149 private:
150 m_datatype m_data{};
151
152 public:
155 template <span_size_type E = Extent, typename std::enable_if<(E == DynamicSpanExtent || E <= 0), int>::type = 0>
156 constexpr span() noexcept {}
157
161 constexpr span(pointer ptr, size_type count): m_data(ptr, count) {
162 GAIA_ASSERT(extent == DynamicSpanExtent || extent == count);
163 }
164
168 constexpr span(pointer begin, pointer end): m_data(begin, end - begin) {
169 GAIA_ASSERT(extent == DynamicSpanExtent || ((uintptr_t)(end - begin) == (uintptr_t)extent));
170 }
171
176 template <
177 span_size_type N, span_size_type E = Extent,
178 typename std::enable_if<
179 (E == DynamicSpanExtent || N == E) &&
180 detail::is_container_element_kind_compatible<element_kind (&)[N], T>::value,
181 int>::type = 0>
182 constexpr span(element_kind (&arr)[N]) noexcept: m_data(arr, N) {}
183
188 template <
189 typename Container, span_size_type E = Extent,
190 typename std::enable_if<
191 E == DynamicSpanExtent && detail::is_container<Container>::value &&
192 detail::is_container_element_kind_compatible<Container&, T>::value,
193 int>::type = 0>
194 constexpr span(Container& cont): m_data(detail::data(cont), detail::size(cont)) {}
195
200 template <
201 typename Container, span_size_type E = Extent,
202 typename std::enable_if<
203 E == DynamicSpanExtent && detail::is_container<Container>::value &&
204 detail::is_container_element_kind_compatible<const Container&, T>::value,
205 int>::type = 0>
206 constexpr span(const Container& cont): m_data(detail::data(cont), detail::size(cont)) {}
207
208 constexpr span(const span&) noexcept = default;
209 constexpr span& operator=(const span&) noexcept = default;
210
215 template <
216 typename T2, span_size_type Extent2,
217 typename std::enable_if<
218 (Extent == DynamicSpanExtent || Extent2 == DynamicSpanExtent || Extent == Extent2) &&
219 std::is_convertible<T2 (*)[], T (*)[]>::value,
220 int>::type = 0>
221 constexpr span(const span<T2, Extent2>& other) noexcept: m_data(other.data(), other.size()) {}
222
223 ~span() noexcept = default;
224
227 GAIA_NODISCARD constexpr pointer data() const noexcept {
228 return m_data.beg;
229 }
230
233 GAIA_NODISCARD constexpr size_type size() const noexcept {
234 return size_type(m_data.end - m_data.beg);
235 }
236
239 GAIA_NODISCARD constexpr bool empty() const noexcept {
240 return m_data.beg == m_data.end;
241 }
242
246 GAIA_NODISCARD constexpr reference operator[](size_type index) const {
247 GAIA_ASSERT((uintptr_t)m_data.beg + index < (uintptr_t)m_data.end);
248 return *(m_data.beg + index);
249 }
250
253 GAIA_NODISCARD constexpr iterator begin() noexcept {
254 return {m_data.beg};
255 }
256
259 GAIA_NODISCARD constexpr iterator begin() const noexcept {
260 return {m_data.beg};
261 }
262
265 GAIA_NODISCARD constexpr const_iterator cbegin() const noexcept {
266 return {m_data.beg};
267 }
268
271 GAIA_NODISCARD constexpr iterator end() noexcept {
272 return {m_data.end};
273 }
274
277 GAIA_NODISCARD constexpr const_iterator end() const noexcept {
278 return {m_data.end};
279 }
280
283 GAIA_NODISCARD constexpr const_iterator cend() const noexcept {
284 return {m_data.end};
285 }
286
290 template <span_size_type Count>
291 GAIA_NODISCARD constexpr span<element_kind, Count> first() const {
292 GAIA_ASSERT(Count <= size());
293 return {m_data.beg, Count};
294 }
295
299 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent> first(size_type count) const {
300 GAIA_ASSERT(count <= size());
301 return {m_data.beg, count};
302 }
303
307 template <span_size_type Count>
308 GAIA_NODISCARD constexpr span<element_kind, Count> last() const {
309 GAIA_ASSERT(Count <= size());
310 return {m_data.beg + (size() - Count), Count};
311 }
312
316 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent> last(size_type count) const {
317 GAIA_ASSERT(count <= size());
318 return {m_data.beg + (size() - count), count};
319 }
320
323 GAIA_NODISCARD constexpr reference front() const {
324 GAIA_ASSERT(!empty());
325 return *m_data.beg;
326 }
327
330 GAIA_NODISCARD constexpr reference back() const {
331 GAIA_ASSERT(!empty());
332 return *(m_data.beg + (size() - 1));
333 }
334
338 template <span_size_type Offset, span_size_type Count = DynamicSpanExtent>
340 T, Count != DynamicSpanExtent ? Count : (Extent != DynamicSpanExtent ? Extent - Offset : DynamicSpanExtent)>;
341
346 template <span_size_type Offset, span_size_type Count = DynamicSpanExtent>
347 GAIA_NODISCARD constexpr subspan_return_t<Offset, Count> subspan() const {
348 GAIA_ASSERT(Offset <= size() && (Count == DynamicSpanExtent || Offset + Count <= size()));
349 return {m_data.beg + Offset, Count != DynamicSpanExtent ? Count : size() - Offset};
350 }
351
356 GAIA_NODISCARD constexpr span<element_kind, DynamicSpanExtent>
357 subspan(size_type offset, size_type count = DynamicSpanExtent) const {
358 GAIA_ASSERT(offset <= size() && (count == DynamicSpanExtent || offset + count <= size()));
359 return {m_data.beg + offset, count != DynamicSpanExtent ? count : size() - offset};
360 }
361 };
362
367 template <typename T, size_t N>
368 span(T (&arr)[N]) -> span<T, N>;
369
374 template <typename T, size_t N>
375 span(gaia::cnt::sarray<T, N>& arr) -> span<T, N>;
376
381 template <typename T, size_t N>
382 span(const gaia::cnt::sarray<T, N>& arr) -> span<const T, N>;
383
387 template <typename Container>
388 span(Container& cont)
389 -> span<typename std::remove_reference<decltype(*detail::data(std::declval<Container&>()))>::type>;
390
394 template <typename Container>
395 span(const Container& cont) -> span<const typename Container::value_type>;
396
403 template <span_size_type N, typename E, span_size_type S>
404 constexpr auto get(span<E, S> s) -> decltype(s[N]) {
405 return s[N];
406 }
407 } // namespace core
408} // namespace gaia
409
411namespace std {
412 template <typename T, size_t Extent>
413 struct tuple_size<gaia::core::span<T, Extent>>: public integral_constant<size_t, Extent> {};
414
415 template <typename T>
416 struct tuple_size<gaia::core::span<T, gaia::core::DynamicSpanExtent>>; // not defined
417
418 template <size_t I, typename T, size_t Extent>
419 struct tuple_element<I, gaia::core::span<T, Extent>> {
420 static_assert(Extent != gaia::core::DynamicSpanExtent && I < Extent, "");
421 using type = T;
422 };
423} // end namespace std
Array with variable size of elements of type.
Definition darray_impl.h:27
Non-owning view over a contiguous sequence of objects.
Definition span_impl.h:110
typename std::remove_cv< T >::type value_type
Element type without const qualification.
Definition span_impl.h:125
constexpr span(const Container &cont)
Constructs a dynamic-extent view over a compatible const container.
Definition span_impl.h:206
GAIA_NODISCARD constexpr iterator begin() noexcept
Returns an iterator to the first element.
Definition span_impl.h:253
constexpr span(element_kind(&arr)[N]) noexcept
Constructs a view over a compatible built-in array.
Definition span_impl.h:182
element_kind * pointer
Pointer to an element.
Definition span_impl.h:131
GAIA_NODISCARD constexpr reference front() const
Returns the first element.
Definition span_impl.h:323
GAIA_NODISCARD constexpr reference back() const
Returns the final element.
Definition span_impl.h:330
const_pointer const_iterator
Const iterator type.
Definition span_impl.h:142
span_size_type size_type
Type used for element counts.
Definition span_impl.h:127
const element_kind * const_pointer
Pointer to a const element.
Definition span_impl.h:133
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:357
GAIA_NODISCARD constexpr const_iterator cend() const noexcept
Returns a const iterator one past the final element.
Definition span_impl.h:283
constexpr span(const span< T2, Extent2 > &other) noexcept
Constructs a compatible span from another element type or extent.
Definition span_impl.h:221
GAIA_NODISCARD constexpr iterator begin() const noexcept
Returns an iterator to the first element.
Definition span_impl.h:259
element_kind & reference
Reference to an element.
Definition span_impl.h:135
pointer iterator
Mutable iterator type.
Definition span_impl.h:140
GAIA_NODISCARD constexpr const_iterator end() const noexcept
Returns a const iterator one past the final element.
Definition span_impl.h:277
span_diff_type difference_type
Type used for iterator differences.
Definition span_impl.h:129
GAIA_NODISCARD constexpr reference operator[](size_type index) const
Returns the element at index.
Definition span_impl.h:246
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:299
const element_kind & const_reference
Reference to a const element.
Definition span_impl.h:137
GAIA_NODISCARD constexpr bool empty() const noexcept
Checks whether the view is empty.
Definition span_impl.h:239
GAIA_NODISCARD constexpr subspan_return_t< Offset, Count > subspan() const
Returns a subspan selected with compile-time offset and count.
Definition span_impl.h:347
GAIA_NODISCARD constexpr size_type size() const noexcept
Returns the number of elements in the view.
Definition span_impl.h:233
GAIA_NODISCARD constexpr span< element_kind, Count > first() const
Returns the first Count elements with a compile-time extent.
Definition span_impl.h:291
T element_kind
Element type, including const qualification.
Definition span_impl.h:123
GAIA_NODISCARD constexpr iterator end() noexcept
Returns an iterator one past the final element.
Definition span_impl.h:271
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:316
constexpr span(Container &cont)
Constructs a dynamic-extent view over a compatible mutable container.
Definition span_impl.h:194
GAIA_NODISCARD constexpr const_iterator cbegin() const noexcept
Returns a const iterator to the first element.
Definition span_impl.h:265
GAIA_NODISCARD constexpr span< element_kind, Count > last() const
Returns the last Count elements with a compile-time extent.
Definition span_impl.h:308