28 #include <type_traits>
43 #if (!defined(_MSC_VER) || _MSC_VER > 1900)
44 #define GUL_SPAN_CONSTEXPR_ASSIGN constexpr
46 #define GUL_SPAN_CONSTEXPR_ASSIGN
49 constexpr std::size_t dynamic_extent = SIZE_MAX;
51 template <
typename ElementType, std::
size_t Extent = dynamic_extent>
56 template <
typename E, std::
size_t S>
58 constexpr span_storage() noexcept = default;
60 constexpr span_storage(E* pointer, std::
size_t ) noexcept : ptr(pointer)
64 static constexpr std::size_t size = S;
68 struct span_storage<E, dynamic_extent> {
69 constexpr span_storage() noexcept = default;
71 constexpr span_storage(E* pointer, std::
size_t sz) noexcept
72 : ptr(pointer), size(sz)
80 constexpr
auto size(
const C& c) -> decltype(c.size())
85 template <
class T, std::
size_t N>
86 constexpr std::size_t size(
const T (&)[N]) noexcept
92 constexpr
auto data(C& c) -> decltype(c.data())
98 constexpr
auto data(
const C& c) -> decltype(c.data())
103 template <
class T, std::
size_t N>
104 constexpr T* data(T (&array)[N]) noexcept
110 constexpr
const E* data(std::initializer_list<E> il) noexcept
116 struct is_span : std::false_type {};
118 template <
typename T, std::
size_t S>
119 struct is_span<span<T, S>> : std::true_type {};
122 struct is_std_array : std::false_type {};
124 template <
typename T, std::
size_t N>
125 struct is_std_array<std::array<T, N>> : std::true_type {};
127 template <
typename,
typename =
void>
128 struct has_size_and_data : std::false_type {};
130 template <
typename T>
131 struct has_size_and_data<T,
void_t<decltype(detail::size(std::declval<T>())),
132 decltype(detail::data(std::declval<T>()))>>
135 template <
typename C,
typename U = remove_cvref_t<C>>
136 struct is_container {
137 static constexpr
bool value =
138 !is_span<U>::value && !is_std_array<U>::value &&
139 !std::is_array<U>::value && has_size_and_data<C>::value;
142 template <
typename T>
143 using remove_pointer_t =
typename std::remove_pointer<T>::type;
145 template <
typename,
typename,
typename =
void>
146 struct is_container_element_type_compatible : std::false_type {};
148 template <
typename T,
typename E>
149 struct is_container_element_type_compatible<
150 T, E,
void_t<decltype(detail::data(std::declval<T>()))>>
151 : std::is_convertible<
152 remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
155 template <
typename,
typename =
size_t>
156 struct is_complete : std::false_type {};
158 template <
typename T>
159 struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
173 template <
typename ElementType, std::
size_t Extent>
175 static_assert(std::is_object<ElementType>::value,
176 "A span's ElementType must be an object type (not a "
177 "reference type or void)");
178 static_assert(detail::is_complete<ElementType>::value,
179 "A span's ElementType must be a complete type (not a forward "
181 static_assert(!std::is_abstract<ElementType>::value,
182 "A span's ElementType cannot be an abstract class type");
184 using storage_type = detail::span_storage<ElementType, Extent>;
189 using value_type =
typename std::remove_cv<ElementType>::type;
206 std::size_t E = Extent,
207 typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
213 : storage_(ptr, count)
218 : storage_(first_elem, last_elem - first_elem)
222 template <std::size_t N, std::size_t E = Extent,
223 typename std::enable_if<
224 (E == dynamic_extent || N == E) &&
225 detail::is_container_element_type_compatible<
232 template <std::size_t N, std::size_t E = Extent,
233 typename std::enable_if<
234 (E == dynamic_extent || N == E) &&
235 detail::is_container_element_type_compatible<
236 std::array<value_type, N>&, ElementType>::value,
238 span(std::array<value_type, N>& arr) noexcept
239 : storage_(arr.data(), N)
243 template <std::size_t N, std::size_t E = Extent,
244 typename std::enable_if<
245 (E == dynamic_extent || N == E) &&
246 detail::is_container_element_type_compatible<
247 const std::array<value_type, N>&, ElementType>::value,
249 span(
const std::array<value_type, N>& arr) noexcept
250 : storage_(arr.data(), N)
255 typename Container, std::size_t E = Extent,
256 typename std::enable_if<
257 E == dynamic_extent && detail::is_container<Container>::value &&
258 detail::is_container_element_type_compatible<
259 Container&, ElementType>::value,
261 constexpr
span(Container& cont)
262 : storage_(detail::
data(cont), detail::
size(cont))
267 typename Container, std::size_t E = Extent,
268 typename std::enable_if<
269 E == dynamic_extent && detail::is_container<Container>::value &&
270 detail::is_container_element_type_compatible<
271 const Container&, ElementType>::value,
273 constexpr
span(
const Container& cont)
274 : storage_(detail::
data(cont), detail::
size(cont))
278 constexpr
span(
const span& other) noexcept =
default;
281 template <
typename OtherElementType, std::size_t OtherExtent,
282 typename std::enable_if<
283 (Extent == OtherExtent || Extent == dynamic_extent) &&
284 std::is_convertible<OtherElementType (*)[],
285 ElementType (*)[]>::value,
288 : storage_(other.data(), other.size())
295 GUL_SPAN_CONSTEXPR_ASSIGN
span&
296 operator=(const
span& other) noexcept = default;
300 template <std::
size_t Count>
303 return {
data(), Count};
307 template <std::
size_t Count>
310 return {
data() + (
size() - Count), Count};
314 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
316 span<ElementType, Count != dynamic_extent
318 : (Extent != dynamic_extent ? Extent - Offset
322 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
325 return {
data() + Offset,
326 Count != dynamic_extent ? Count :
size() - Offset};
333 return {
data(), count};
340 return {
data() + (
size() - count), count};
347 return {
data() + offset,
348 count == dynamic_extent ?
size() - offset : count};
362 constexpr
bool empty() const noexcept
371 return *(
data() + idx);
433 storage_type storage_{};
442 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
443 constexpr
bool operator==(span<T, X> lhs, span<U, Y> rhs)
445 if (lhs.size() != rhs.size()) {
449 for (std::size_t i = 0; i < lhs.size(); i++) {
450 if (lhs[i] != rhs[i]) {
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)
461 return !(lhs == rhs);
464 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
465 constexpr
bool operator<(span<T, X> lhs, span<U, Y> rhs)
468 const std::size_t size = lhs.size() < rhs.size() ? lhs.size() : rhs.size();
470 for (std::size_t i = 0; i < size; i++) {
471 if (lhs[i] < rhs[i]) {
474 if (lhs[i] > rhs[i]) {
478 return lhs.size() < rhs.size();
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)
493 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
494 constexpr
bool operator>=(span<T, X> lhs, span<U, Y> rhs)
509 template <
typename ElementType, std::
size_t Extent>
510 span<
const unsigned char, ((Extent == dynamic_extent) ? dynamic_extent
511 :
sizeof(ElementType) * Extent)>
514 return {
reinterpret_cast<const unsigned char *
>(s.
data()), s.
size_bytes()};
526 class ElementType,
size_t Extent,
527 typename std::enable_if<!std::is_const<ElementType>::value,
int>::type = 0>
528 span<
unsigned char, ((Extent == dynamic_extent) ? dynamic_extent
529 :
sizeof(ElementType) * Extent)>
532 return {
reinterpret_cast<unsigned char *
>(s.
data()), s.
size_bytes()};
543 template <std::
size_t N,
typename E, std::
size_t S>
556 template <
typename ElementType,
size_t Extent>
557 class tuple_size<
gul14::span<ElementType, Extent>>
558 :
public integral_constant<size_t, Extent> {};
560 template <
typename ElementType>
561 class tuple_size<
gul14::span<ElementType, gul14::dynamic_extent>>;
563 template <size_t I, typename ElementType, size_t Extent>
564 class tuple_element<I, gul14::span<ElementType, Extent>> {
566 static_assert(Extent != gul14::dynamic_extent && I < Extent,
"");
567 using type = ElementType;
A view to a contiguous sequence of objects.
Definition: span.h:174
element_type & reference
See std::span.
Definition: span.h:194
constexpr span(element_type(&arr)[N]) noexcept
See std::span.
Definition: span.h:228
reverse_iterator rend() const noexcept
See std::span.
Definition: span.h:409
constexpr friend iterator end(span s) noexcept
See std::span.
Definition: span.h:430
std::size_t index_type
See std::span.
Definition: span.h:190
std::reverse_iterator< iterator > reverse_iterator
See std::span.
Definition: span.h:197
span(const std::array< value_type, N > &arr) noexcept
See std::span.
Definition: span.h:249
constexpr span(Container &cont)
See std::span.
Definition: span.h:261
constexpr reference operator[](index_type idx) const
See std::span.
Definition: span.h:369
constexpr span() noexcept
See std::span.
Definition: span.h:208
~span() noexcept=default
See std::span.
constexpr span< element_type, dynamic_extent > first(index_type count) const
See std::span.
Definition: span.h:331
element_type * pointer
See std::span.
Definition: span.h:192
constexpr friend iterator begin(span s) noexcept
See std::span.
Definition: span.h:427
constexpr index_type size() const noexcept
See std::span.
Definition: span.h:353
constexpr span< element_type, dynamic_extent > subspan(index_type offset, index_type count=dynamic_extent) const
See std::span.
Definition: span.h:345
std::reverse_iterator< const_iterator > const_reverse_iterator
See std::span.
Definition: span.h:198
constexpr span(const Container &cont)
See std::span.
Definition: span.h:273
constexpr span(const span &other) noexcept=default
See std::span.
const element_type * const_pointer
See std::span.
Definition: span.h:193
const_pointer const_iterator
See std::span.
Definition: span.h:196
constexpr bool empty() const noexcept
See std::span.
Definition: span.h:362
ElementType element_type
See std::span.
Definition: span.h:188
constexpr span< element_type, Count > first() const
See std::span.
Definition: span.h:301
constexpr span< element_type, dynamic_extent > last(index_type count) const
See std::span.
Definition: span.h:338
constexpr iterator end() const noexcept
See std::span.
Definition: span.h:394
constexpr const_iterator cbegin() const noexcept
See std::span.
Definition: span.h:397
const_reverse_iterator crbegin() const noexcept
See std::span.
Definition: span.h:415
pointer iterator
See std::span.
Definition: span.h:195
constexpr reference back() const
See std::span.
Definition: span.h:381
constexpr subspan_return_t< Offset, Count > subspan() const
See std::span.
Definition: span.h:323
static constexpr index_type extent
See std::span.
Definition: span.h:201
typename std::remove_cv< ElementType >::type value_type
See std::span.
Definition: span.h:189
constexpr reference front() const
See std::span.
Definition: span.h:375
constexpr iterator begin() const noexcept
See std::span.
Definition: span.h:391
constexpr pointer data() const noexcept
See std::span.
Definition: span.h:387
constexpr span(pointer ptr, index_type count)
See std::span.
Definition: span.h:212
span(std::array< value_type, N > &arr) noexcept
See std::span.
Definition: span.h:238
std::ptrdiff_t difference_type
See std::span.
Definition: span.h:191
reverse_iterator rbegin() const noexcept
See std::span.
Definition: span.h:403
constexpr const_iterator cend() const noexcept
See std::span.
Definition: span.h:400
constexpr span(const span< OtherElementType, OtherExtent > &other) noexcept
See std::span.
Definition: span.h:287
constexpr span< element_type, Count > last() const
See std::span.
Definition: span.h:308
constexpr index_type size_bytes() const noexcept
See std::span.
Definition: span.h:356
constexpr span(pointer first_elem, pointer last_elem)
See std::span.
Definition: span.h:217
const_reverse_iterator crend() const noexcept
See std::span.
Definition: span.h:421
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:544
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:512
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:530
void void_t
A type mapping an arbitrary list of types to void (for SFINAE).
Definition: traits.h:92
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
Some metaprogramming traits for the General Utility Library.