28 #include <type_traits>
37 #if (!defined(_MSC_VER) || _MSC_VER > 1900)
38 #define GUL_SPAN_CONSTEXPR_ASSIGN constexpr
40 #define GUL_SPAN_CONSTEXPR_ASSIGN
43 constexpr std::size_t dynamic_extent = SIZE_MAX;
45 template <
typename ElementType, std::
size_t Extent = dynamic_extent>
50 template <
typename E, std::
size_t S>
52 constexpr span_storage() noexcept = default;
54 constexpr span_storage(E* pointer, std::
size_t ) noexcept : ptr(pointer)
58 static constexpr std::size_t size = S;
62 struct span_storage<E, dynamic_extent> {
63 constexpr span_storage() noexcept = default;
65 constexpr span_storage(E* pointer, std::
size_t sz) noexcept
66 : ptr(pointer), size(sz)
74 constexpr
auto size(
const C& c) -> decltype(c.size())
79 template <
class T, std::
size_t N>
80 constexpr std::size_t size(
const T (&)[N]) noexcept
86 constexpr
auto data(C& c) -> decltype(c.data())
92 constexpr
auto data(
const C& c) -> decltype(c.data())
97 template <
class T, std::
size_t N>
98 constexpr T* data(T (&array)[N]) noexcept
104 constexpr
const E* data(std::initializer_list<E> il) noexcept
110 struct is_span : std::false_type {};
112 template <
typename T, std::
size_t S>
113 struct is_span<span<T, S>> : std::true_type {};
116 struct is_std_array : std::false_type {};
118 template <
typename T, std::
size_t N>
119 struct is_std_array<std::array<T, N>> : std::true_type {};
121 template <
typename,
typename =
void>
122 struct has_size_and_data : std::false_type {};
124 template <
typename T>
125 struct has_size_and_data<T,
void_t<decltype(detail::size(std::declval<T>())),
126 decltype(detail::data(std::declval<T>()))>>
129 template <
typename C,
typename U = remove_cvref_t<C>>
130 struct is_container {
131 static constexpr
bool value =
132 !is_span<U>::value && !is_std_array<U>::value &&
133 !std::is_array<U>::value && has_size_and_data<C>::value;
136 template <
typename T>
137 using remove_pointer_t =
typename std::remove_pointer<T>::type;
139 template <
typename,
typename,
typename =
void>
140 struct is_container_element_type_compatible : std::false_type {};
142 template <
typename T,
typename E>
143 struct is_container_element_type_compatible<
144 T, E,
void_t<decltype(detail::data(std::declval<T>()))>>
145 : std::is_convertible<
146 remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
149 template <
typename,
typename =
size_t>
150 struct is_complete : std::false_type {};
152 template <
typename T>
153 struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
167 template <
typename ElementType, std::
size_t Extent>
169 static_assert(std::is_object<ElementType>::value,
170 "A span's ElementType must be an object type (not a "
171 "reference type or void)");
172 static_assert(detail::is_complete<ElementType>::value,
173 "A span's ElementType must be a complete type (not a forward "
175 static_assert(!std::is_abstract<ElementType>::value,
176 "A span's ElementType cannot be an abstract class type");
178 using storage_type = detail::span_storage<ElementType, Extent>;
183 using value_type =
typename std::remove_cv<ElementType>::type;
200 std::size_t E = Extent,
201 typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
207 : storage_(ptr, count)
212 : storage_(first_elem, last_elem - first_elem)
216 template <std::size_t N, std::size_t E = Extent,
217 typename std::enable_if<
218 (E == dynamic_extent || N == E) &&
219 detail::is_container_element_type_compatible<
226 template <std::size_t N, std::size_t E = Extent,
227 typename std::enable_if<
228 (E == dynamic_extent || N == E) &&
229 detail::is_container_element_type_compatible<
230 std::array<value_type, N>&, ElementType>::value,
232 span(std::array<value_type, N>& arr) noexcept
233 : storage_(arr.data(), N)
237 template <std::size_t N, std::size_t E = Extent,
238 typename std::enable_if<
239 (E == dynamic_extent || N == E) &&
240 detail::is_container_element_type_compatible<
241 const std::array<value_type, N>&, ElementType>::value,
243 span(
const std::array<value_type, N>& arr) noexcept
244 : storage_(arr.data(), N)
249 typename Container, std::size_t E = Extent,
250 typename std::enable_if<
251 E == dynamic_extent && detail::is_container<Container>::value &&
252 detail::is_container_element_type_compatible<
253 Container&, ElementType>::value,
255 constexpr
span(Container& cont)
256 : storage_(detail::
data(cont), detail::
size(cont))
261 typename Container, std::size_t E = Extent,
262 typename std::enable_if<
263 E == dynamic_extent && detail::is_container<Container>::value &&
264 detail::is_container_element_type_compatible<
265 const Container&, ElementType>::value,
267 constexpr
span(
const Container& cont)
268 : storage_(detail::
data(cont), detail::
size(cont))
272 constexpr
span(
const span& other) noexcept =
default;
275 template <
typename OtherElementType, std::size_t OtherExtent,
276 typename std::enable_if<
277 (Extent == OtherExtent || Extent == dynamic_extent) &&
278 std::is_convertible<OtherElementType (*)[],
279 ElementType (*)[]>::value,
282 : storage_(other.data(), other.size())
289 GUL_SPAN_CONSTEXPR_ASSIGN
span&
290 operator=(const
span& other) noexcept = default;
294 template <std::
size_t Count>
297 return {
data(), Count};
301 template <std::
size_t Count>
304 return {
data() + (
size() - Count), Count};
308 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
310 span<ElementType, Count != dynamic_extent
312 : (Extent != dynamic_extent ? Extent - Offset
316 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
319 return {
data() + Offset,
320 Count != dynamic_extent ? Count :
size() - Offset};
327 return {
data(), count};
334 return {
data() + (
size() - count), count};
341 return {
data() + offset,
342 count == dynamic_extent ?
size() - offset : count};
356 constexpr
bool empty() const noexcept
365 return *(
data() + idx);
427 storage_type storage_{};
436 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
437 constexpr
bool operator==(span<T, X> lhs, span<U, Y> rhs)
439 if (lhs.size() != rhs.size()) {
443 for (std::size_t i = 0; i < lhs.size(); i++) {
444 if (lhs[i] != rhs[i]) {
452 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
453 constexpr
bool operator!=(span<T, X> lhs, span<U, Y> rhs)
455 return !(lhs == rhs);
458 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
459 constexpr
bool operator<(span<T, X> lhs, span<U, Y> rhs)
462 const std::size_t size = lhs.size() < rhs.size() ? lhs.size() : rhs.size();
464 for (std::size_t i = 0; i < size; i++) {
465 if (lhs[i] < rhs[i]) {
468 if (lhs[i] > rhs[i]) {
472 return lhs.size() < rhs.size();
475 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
476 constexpr
bool operator<=(span<T, X> lhs, span<U, Y> rhs)
481 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
482 constexpr
bool operator>(span<T, X> lhs, span<U, Y> rhs)
487 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
488 constexpr
bool operator>=(span<T, X> lhs, span<U, Y> rhs)
503 template <
typename ElementType, std::
size_t Extent>
504 span<
const unsigned char, ((Extent == dynamic_extent) ? dynamic_extent
505 :
sizeof(ElementType) * Extent)>
508 return {
reinterpret_cast<const unsigned char *
>(s.
data()), s.
size_bytes()};
520 class ElementType,
size_t Extent,
521 typename std::enable_if<!std::is_const<ElementType>::value,
int>::type = 0>
522 span<
unsigned char, ((Extent == dynamic_extent) ? dynamic_extent
523 :
sizeof(ElementType) * Extent)>
526 return {
reinterpret_cast<unsigned char *
>(s.
data()), s.
size_bytes()};
537 template <std::
size_t N,
typename E, std::
size_t S>
548 template <
typename ElementType,
size_t Extent>
549 class tuple_size<
gul14::span<ElementType, Extent>>
550 :
public integral_constant<size_t, Extent> {};
552 template <
typename ElementType>
553 class tuple_size<
gul14::span<ElementType, gul14::dynamic_extent>>;
555 template <size_t I, typename ElementType, size_t Extent>
556 class tuple_element<I, gul14::span<ElementType, Extent>> {
558 static_assert(Extent != gul14::dynamic_extent && I < Extent,
"");
559 using type = ElementType;
A view to a contiguous sequence of objects.
Definition: span.h:168
element_type & reference
See std::span.
Definition: span.h:188
constexpr span(element_type(&arr)[N]) noexcept
See std::span.
Definition: span.h:222
reverse_iterator rend() const noexcept
See std::span.
Definition: span.h:403
constexpr friend iterator end(span s) noexcept
See std::span.
Definition: span.h:424
std::size_t index_type
See std::span.
Definition: span.h:184
std::reverse_iterator< iterator > reverse_iterator
See std::span.
Definition: span.h:191
span(const std::array< value_type, N > &arr) noexcept
See std::span.
Definition: span.h:243
constexpr span(Container &cont)
See std::span.
Definition: span.h:255
constexpr reference operator[](index_type idx) const
See std::span.
Definition: span.h:363
constexpr span() noexcept
See std::span.
Definition: span.h:202
~span() noexcept=default
See std::span.
constexpr span< element_type, dynamic_extent > first(index_type count) const
See std::span.
Definition: span.h:325
element_type * pointer
See std::span.
Definition: span.h:186
constexpr friend iterator begin(span s) noexcept
See std::span.
Definition: span.h:421
constexpr index_type size() const noexcept
See std::span.
Definition: span.h:347
constexpr span< element_type, dynamic_extent > subspan(index_type offset, index_type count=dynamic_extent) const
See std::span.
Definition: span.h:339
std::reverse_iterator< const_iterator > const_reverse_iterator
See std::span.
Definition: span.h:192
constexpr span(const Container &cont)
See std::span.
Definition: span.h:267
constexpr span(const span &other) noexcept=default
See std::span.
const element_type * const_pointer
See std::span.
Definition: span.h:187
const_pointer const_iterator
See std::span.
Definition: span.h:190
constexpr bool empty() const noexcept
See std::span.
Definition: span.h:356
ElementType element_type
See std::span.
Definition: span.h:182
constexpr span< element_type, Count > first() const
See std::span.
Definition: span.h:295
constexpr span< element_type, dynamic_extent > last(index_type count) const
See std::span.
Definition: span.h:332
constexpr iterator end() const noexcept
See std::span.
Definition: span.h:388
constexpr const_iterator cbegin() const noexcept
See std::span.
Definition: span.h:391
const_reverse_iterator crbegin() const noexcept
See std::span.
Definition: span.h:409
pointer iterator
See std::span.
Definition: span.h:189
constexpr reference back() const
See std::span.
Definition: span.h:375
constexpr subspan_return_t< Offset, Count > subspan() const
See std::span.
Definition: span.h:317
static constexpr index_type extent
See std::span.
Definition: span.h:195
typename std::remove_cv< ElementType >::type value_type
See std::span.
Definition: span.h:183
constexpr reference front() const
See std::span.
Definition: span.h:369
constexpr iterator begin() const noexcept
See std::span.
Definition: span.h:385
constexpr pointer data() const noexcept
See std::span.
Definition: span.h:381
constexpr span(pointer ptr, index_type count)
See std::span.
Definition: span.h:206
span(std::array< value_type, N > &arr) noexcept
See std::span.
Definition: span.h:232
std::ptrdiff_t difference_type
See std::span.
Definition: span.h:185
reverse_iterator rbegin() const noexcept
See std::span.
Definition: span.h:397
constexpr const_iterator cend() const noexcept
See std::span.
Definition: span.h:394
constexpr span(const span< OtherElementType, OtherExtent > &other) noexcept
See std::span.
Definition: span.h:281
constexpr span< element_type, Count > last() const
See std::span.
Definition: span.h:302
constexpr index_type size_bytes() const noexcept
See std::span.
Definition: span.h:350
constexpr span(pointer first_elem, pointer last_elem)
See std::span.
Definition: span.h:211
const_reverse_iterator crend() const noexcept
See std::span.
Definition: span.h:415
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
void void_t
A type mapping an arbitrary list of types to void (for SFINAE).
Definition: traits.h:92
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:538
span< const unsigned char,((Extent==dynamic_extent) ? dynamic_extent :sizeof(ElementType) *Extent)> as_bytes(span< ElementType, Extent > s) noexcept
Return a constant view to the byte representation of the elements of a given span.
Definition: span.h:506
span< unsigned char,((Extent==dynamic_extent) ? dynamic_extent :sizeof(ElementType) *Extent)> as_writable_bytes(span< ElementType, Extent > s) noexcept
Return a writable view to the byte representation of the elements of a given span.
Definition: span.h:524
Some metaprogramming traits for the General Utility Library.