28 #include <type_traits>
35 #if (!defined(_MSC_VER) || _MSC_VER > 1900)
36 #define GUL_SPAN_CONSTEXPR_ASSIGN constexpr
38 #define GUL_SPAN_CONSTEXPR_ASSIGN
41 constexpr std::size_t dynamic_extent = SIZE_MAX;
43 template <
typename ElementType, std::
size_t Extent = dynamic_extent>
48 template <
typename E, std::
size_t S>
50 constexpr span_storage() noexcept = default;
52 constexpr span_storage(E* pointer, std::
size_t ) noexcept : ptr(pointer)
56 static constexpr std::size_t size = S;
60 struct span_storage<E, dynamic_extent> {
61 constexpr span_storage() noexcept = default;
63 constexpr span_storage(E* pointer, std::
size_t sz) noexcept
64 : ptr(pointer), size(sz)
72 constexpr
auto size(
const C& c) -> decltype(c.size())
77 template <
class T, std::
size_t N>
78 constexpr std::size_t size(
const T (&)[N]) noexcept
84 constexpr
auto data(C& c) -> decltype(c.data())
90 constexpr
auto data(
const C& c) -> decltype(c.data())
95 template <
class T, std::
size_t N>
96 constexpr T* data(T (&array)[N]) noexcept
102 constexpr
const E* data(std::initializer_list<E> il) noexcept
107 template <
typename...>
110 template <
typename T>
111 using uncvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
114 struct is_span : std::false_type {};
116 template <
typename T, std::
size_t S>
117 struct is_span<span<T, S>> : std::true_type {};
120 struct is_std_array : std::false_type {};
122 template <
typename T, std::
size_t N>
123 struct is_std_array<std::array<T, N>> : std::true_type {};
125 template <
typename,
typename =
void>
126 struct has_size_and_data : std::false_type {};
128 template <
typename T>
129 struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())),
130 decltype(detail::data(std::declval<T>()))>>
133 template <
typename C,
typename U = uncvref_t<C>>
134 struct is_container {
135 static constexpr
bool value =
136 !is_span<U>::value && !is_std_array<U>::value &&
137 !std::is_array<U>::value && has_size_and_data<C>::value;
140 template <
typename T>
141 using remove_pointer_t =
typename std::remove_pointer<T>::type;
143 template <
typename,
typename,
typename =
void>
144 struct is_container_element_type_compatible : std::false_type {};
146 template <
typename T,
typename E>
147 struct is_container_element_type_compatible<
148 T, E, void_t<decltype(detail::data(std::declval<T>()))>>
149 : std::is_convertible<
150 remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
153 template <
typename,
typename =
size_t>
154 struct is_complete : std::false_type {};
156 template <
typename T>
157 struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
171 template <
typename ElementType, std::
size_t Extent>
173 static_assert(std::is_object<ElementType>::value,
174 "A span's ElementType must be an object type (not a "
175 "reference type or void)");
176 static_assert(detail::is_complete<ElementType>::value,
177 "A span's ElementType must be a complete type (not a forward "
179 static_assert(!std::is_abstract<ElementType>::value,
180 "A span's ElementType cannot be an abstract class type");
182 using storage_type = detail::span_storage<ElementType, Extent>;
187 using value_type =
typename std::remove_cv<ElementType>::type;
204 std::size_t E = Extent,
205 typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
211 : storage_(ptr, count)
216 : storage_(first_elem, last_elem - first_elem)
220 template <std::size_t N, std::size_t E = Extent,
221 typename std::enable_if<
222 (E == dynamic_extent || N == E) &&
223 detail::is_container_element_type_compatible<
230 template <std::size_t N, std::size_t E = Extent,
231 typename std::enable_if<
232 (E == dynamic_extent || N == E) &&
233 detail::is_container_element_type_compatible<
234 std::array<value_type, N>&, ElementType>::value,
236 span(std::array<value_type, N>& arr) noexcept
237 : storage_(arr.data(), N)
241 template <std::size_t N, std::size_t E = Extent,
242 typename std::enable_if<
243 (E == dynamic_extent || N == E) &&
244 detail::is_container_element_type_compatible<
245 const std::array<value_type, N>&, ElementType>::value,
247 span(
const std::array<value_type, N>& arr) noexcept
248 : storage_(arr.data(), N)
253 typename Container, std::size_t E = Extent,
254 typename std::enable_if<
255 E == dynamic_extent && detail::is_container<Container>::value &&
256 detail::is_container_element_type_compatible<
257 Container&, ElementType>::value,
259 constexpr
span(Container& cont)
260 : storage_(detail::
data(cont), detail::
size(cont))
265 typename Container, std::size_t E = Extent,
266 typename std::enable_if<
267 E == dynamic_extent && detail::is_container<Container>::value &&
268 detail::is_container_element_type_compatible<
269 const Container&, ElementType>::value,
271 constexpr
span(
const Container& cont)
272 : storage_(detail::
data(cont), detail::
size(cont))
276 constexpr
span(
const span& other) noexcept =
default;
279 template <
typename OtherElementType, std::size_t OtherExtent,
280 typename std::enable_if<
281 (Extent == OtherExtent || Extent == dynamic_extent) &&
282 std::is_convertible<OtherElementType (*)[],
283 ElementType (*)[]>::value,
286 : storage_(other.data(), other.size())
293 GUL_SPAN_CONSTEXPR_ASSIGN
span&
294 operator=(const
span& other) noexcept = default;
298 template <std::
size_t Count>
301 return {
data(), Count};
305 template <std::
size_t Count>
308 return {
data() + (
size() - Count), Count};
312 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
314 span<ElementType, Count != dynamic_extent
316 : (Extent != dynamic_extent ? Extent - Offset
320 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
323 return {
data() + Offset,
324 Count != dynamic_extent ? Count :
size() - Offset};
331 return {
data(), count};
338 return {
data() + (
size() - count), count};
345 return {
data() + offset,
346 count == dynamic_extent ?
size() - offset : count};
360 constexpr
bool empty() const noexcept
369 return *(
data() + idx);
431 storage_type storage_{};
440 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
441 constexpr
bool operator==(span<T, X> lhs, span<U, Y> rhs)
443 if (lhs.size() != rhs.size()) {
447 for (std::size_t i = 0; i < lhs.size(); i++) {
448 if (lhs[i] != rhs[i]) {
456 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
457 constexpr
bool operator!=(span<T, X> lhs, span<U, Y> rhs)
459 return !(lhs == rhs);
462 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
463 constexpr
bool operator<(span<T, X> lhs, span<U, Y> rhs)
466 const std::size_t size = lhs.size() < rhs.size() ? lhs.size() : rhs.size();
468 for (std::size_t i = 0; i < size; i++) {
469 if (lhs[i] < rhs[i]) {
472 if (lhs[i] > rhs[i]) {
476 return lhs.size() < rhs.size();
479 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
480 constexpr
bool operator<=(span<T, X> lhs, span<U, Y> rhs)
485 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
486 constexpr
bool operator>(span<T, X> lhs, span<U, Y> rhs)
491 template <
typename T, std::
size_t X,
typename U, std::
size_t Y>
492 constexpr
bool operator>=(span<T, X> lhs, span<U, Y> rhs)
507 template <
typename ElementType, std::
size_t Extent>
508 span<
const unsigned char, ((Extent == dynamic_extent) ? dynamic_extent
509 :
sizeof(ElementType) * Extent)>
512 return {
reinterpret_cast<const unsigned char *
>(s.
data()), s.
size_bytes()};
524 class ElementType,
size_t Extent,
525 typename std::enable_if<!std::is_const<ElementType>::value,
int>::type = 0>
526 span<
unsigned char, ((Extent == dynamic_extent) ? dynamic_extent
527 :
sizeof(ElementType) * Extent)>
530 return {
reinterpret_cast<unsigned char *
>(s.
data()), s.
size_bytes()};
541 template <std::
size_t N,
typename E, std::
size_t S>
552 template <
typename ElementType,
size_t Extent>
553 class tuple_size<
gul14::span<ElementType, Extent>>
554 :
public integral_constant<size_t, Extent> {};
556 template <
typename ElementType>
557 class tuple_size<
gul14::span<ElementType, gul14::dynamic_extent>>;
559 template <size_t I, typename ElementType, size_t Extent>
560 class tuple_element<I, gul14::span<ElementType, Extent>> {
562 static_assert(Extent != gul14::dynamic_extent && I < Extent,
"");
563 using type = ElementType;
A view to a contiguous sequence of objects.
Definition: span.h:172
element_type & reference
See std::span.
Definition: span.h:192
constexpr span(element_type(&arr)[N]) noexcept
See std::span.
Definition: span.h:226
reverse_iterator rend() const noexcept
See std::span.
Definition: span.h:407
constexpr friend iterator end(span s) noexcept
See std::span.
Definition: span.h:428
std::size_t index_type
See std::span.
Definition: span.h:188
std::reverse_iterator< iterator > reverse_iterator
See std::span.
Definition: span.h:195
span(const std::array< value_type, N > &arr) noexcept
See std::span.
Definition: span.h:247
constexpr span(Container &cont)
See std::span.
Definition: span.h:259
constexpr reference operator[](index_type idx) const
See std::span.
Definition: span.h:367
constexpr span() noexcept
See std::span.
Definition: span.h:206
~span() noexcept=default
See std::span.
constexpr span< element_type, dynamic_extent > first(index_type count) const
See std::span.
Definition: span.h:329
element_type * pointer
See std::span.
Definition: span.h:190
constexpr friend iterator begin(span s) noexcept
See std::span.
Definition: span.h:425
constexpr index_type size() const noexcept
See std::span.
Definition: span.h:351
constexpr span< element_type, dynamic_extent > subspan(index_type offset, index_type count=dynamic_extent) const
See std::span.
Definition: span.h:343
std::reverse_iterator< const_iterator > const_reverse_iterator
See std::span.
Definition: span.h:196
constexpr span(const Container &cont)
See std::span.
Definition: span.h:271
constexpr span(const span &other) noexcept=default
See std::span.
const element_type * const_pointer
See std::span.
Definition: span.h:191
const_pointer const_iterator
See std::span.
Definition: span.h:194
constexpr bool empty() const noexcept
See std::span.
Definition: span.h:360
ElementType element_type
See std::span.
Definition: span.h:186
constexpr span< element_type, Count > first() const
See std::span.
Definition: span.h:299
constexpr span< element_type, dynamic_extent > last(index_type count) const
See std::span.
Definition: span.h:336
constexpr iterator end() const noexcept
See std::span.
Definition: span.h:392
constexpr const_iterator cbegin() const noexcept
See std::span.
Definition: span.h:395
const_reverse_iterator crbegin() const noexcept
See std::span.
Definition: span.h:413
pointer iterator
See std::span.
Definition: span.h:193
constexpr reference back() const
See std::span.
Definition: span.h:379
constexpr subspan_return_t< Offset, Count > subspan() const
See std::span.
Definition: span.h:321
static constexpr index_type extent
See std::span.
Definition: span.h:199
typename std::remove_cv< ElementType >::type value_type
See std::span.
Definition: span.h:187
constexpr reference front() const
See std::span.
Definition: span.h:373
constexpr iterator begin() const noexcept
See std::span.
Definition: span.h:389
constexpr pointer data() const noexcept
See std::span.
Definition: span.h:385
constexpr span(pointer ptr, index_type count)
See std::span.
Definition: span.h:210
span(std::array< value_type, N > &arr) noexcept
See std::span.
Definition: span.h:236
std::ptrdiff_t difference_type
See std::span.
Definition: span.h:189
reverse_iterator rbegin() const noexcept
See std::span.
Definition: span.h:401
constexpr const_iterator cend() const noexcept
See std::span.
Definition: span.h:398
constexpr span(const span< OtherElementType, OtherExtent > &other) noexcept
See std::span.
Definition: span.h:285
constexpr span< element_type, Count > last() const
See std::span.
Definition: span.h:306
constexpr index_type size_bytes() const noexcept
See std::span.
Definition: span.h:354
constexpr span(pointer first_elem, pointer last_elem)
See std::span.
Definition: span.h:215
const_reverse_iterator crend() const noexcept
See std::span.
Definition: span.h:419
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:542
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:510
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:528