45#include "pw_span/internal/config.h"
52inline constexpr size_t dynamic_extent = std::numeric_limits<size_t>::max();
54template <
typename T,
size_t Extent = dynamic_extent>
57namespace pw_span_internal {
60struct ExtentImpl : std::integral_constant<size_t, dynamic_extent> {};
62template <
typename T,
size_t N>
63struct ExtentImpl<T[N]> : std::integral_constant<size_t, N> {};
65template <
typename T,
size_t N>
66struct ExtentImpl<std::array<T, N>> : std::integral_constant<size_t, N> {};
68template <
typename T,
size_t N>
77template <
typename T,
size_t Extent>
86template <
typename T,
size_t N>
93using IsCArray = std::is_array<std::remove_reference_t<T>>;
95template <
typename From,
typename To>
96using IsLegalDataConversion = std::is_convertible<From (*)[], To (*)[]>;
98template <
typename Container,
typename T>
99using ContainerHasConvertibleData = IsLegalDataConversion<
100 std::remove_pointer_t<decltype(std::data(std::declval<Container>()))>,
103template <
typename Container>
104using ContainerHasIntegralSize =
105 std::is_integral<decltype(std::size(std::declval<Container>()))>;
107template <
typename From,
size_t FromExtent,
typename To,
size_t ToExtent>
108using EnableIfLegalSpanConversion =
109 std::enable_if_t<(ToExtent == dynamic_extent || ToExtent == FromExtent) &&
110 IsLegalDataConversion<From, To>::value>;
113template <
typename Array,
typename T,
size_t Extent>
114using EnableIfSpanCompatibleArray =
115 std::enable_if_t<(
Extent == dynamic_extent ||
117 ContainerHasConvertibleData<Array, T>::value>;
120template <
typename Container,
typename T>
121using IsSpanCompatibleContainer =
122 std::conditional_t<!IsSpan<Container>::value &&
124 !IsCArray<Container>::value &&
125 ContainerHasConvertibleData<Container, T>::value &&
126 ContainerHasIntegralSize<Container>::value,
130template <
typename Container,
typename T>
131using EnableIfSpanCompatibleContainer =
132 std::enable_if_t<IsSpanCompatibleContainer<Container, T>::value>;
134template <
typename Container,
typename T,
size_t Extent>
135using EnableIfSpanCompatibleContainerAndSpanIsDynamic =
136 std::enable_if_t<IsSpanCompatibleContainer<Container, T>::value &&
137 Extent == dynamic_extent>;
142template <
size_t Extent>
146 constexpr size_t size()
const noexcept {
return Extent; }
153 constexpr explicit ExtentStorage(
size_t size) noexcept : size_(size) {}
154 constexpr size_t size()
const noexcept {
return size_; }
234template <
typename T,
size_t Extent>
240 using element_type = T;
241 using value_type = std::remove_cv_t<T>;
242 using size_type = size_t;
243 using difference_type = ptrdiff_t;
245 using reference = T&;
247 using reverse_iterator = std::reverse_iterator<iterator>;
248 static constexpr size_t extent = Extent;
252 static_assert(Extent == dynamic_extent || Extent == 0,
"Invalid Extent");
255 constexpr span(T* data,
size_t size) noexcept
257 _PW_SPAN_ASSERT(Extent == dynamic_extent || Extent == size);
261 constexpr span(std::nullptr_t data,
size_t size) =
delete;
264 template <
typename =
void>
265 constexpr span(T* begin, T* end) noexcept
266 :
span(begin,
static_cast<size_t>(end - begin)) {
268 _PW_SPAN_ASSERT(begin <= end);
274 pw_span_internal::EnableIfSpanCompatibleArray<T (&)[N], T, Extent>>
275 constexpr span(T (&array)[N]) noexcept :
span(std::data(array), N) {}
277 template <
typename U,
279 typename = pw_span_internal::
280 EnableIfSpanCompatibleArray<std::array<U, N>&, T, Extent>>
281 constexpr span(std::array<U, N>& array) noexcept
282 :
span(std::data(array), N) {}
284 template <
typename U,
286 typename = pw_span_internal::
287 EnableIfSpanCompatibleArray<const std::array<U, N>&, T, Extent>>
288 constexpr span(
const std::array<U, N>& array) noexcept
289 :
span(std::data(array), N) {}
293 template <
typename Container,
294 typename = pw_span_internal::
295 EnableIfSpanCompatibleContainerAndSpanIsDynamic<Container&,
298 constexpr span(Container& container) noexcept
299 :
span(std::data(container), std::size(container)) {}
303 typename = pw_span_internal::
304 EnableIfSpanCompatibleContainerAndSpanIsDynamic<
const Container&,
307 constexpr span(
const Container& container) noexcept
308 :
span(std::data(container), std::size(container)) {}
310 constexpr span(
const span& other)
noexcept =
default;
315 template <
typename U,
317 typename = pw_span_internal::
318 EnableIfLegalSpanConversion<U, OtherExtent, T, Extent>>
320 :
span(other.data(), other.size()) {}
322 constexpr span& operator=(
const span& other)
noexcept =
default;
323 ~span()
noexcept =
default;
326 template <
size_t Count>
328 static_assert(Count <= Extent,
"Count must not exceed Extent");
329 _PW_SPAN_ASSERT(Extent != dynamic_extent || Count <= size());
330 return {data(), Count};
333 template <
size_t Count>
335 static_assert(Count <= Extent,
"Count must not exceed Extent");
336 _PW_SPAN_ASSERT(Extent != dynamic_extent || Count <= size());
337 return {data() + (size() - Count), Count};
340 template <
size_t Offset,
size_t Count = dynamic_extent>
342 (Count != dynamic_extent
344 : (Extent != dynamic_extent ? Extent - Offset
346 subspan()
const noexcept {
347 static_assert(Offset <= Extent,
"Offset must not exceed Extent");
348 static_assert(Count == dynamic_extent || Count <= Extent - Offset,
349 "Count must not exceed Extent - Offset");
350 _PW_SPAN_ASSERT(Extent != dynamic_extent || Offset <= size());
351 _PW_SPAN_ASSERT(Extent != dynamic_extent || Count == dynamic_extent ||
352 Count <= size() - Offset);
353 return {data() + Offset, Count != dynamic_extent ? Count : size() - Offset};
358 _PW_SPAN_ASSERT(count <= size());
359 return {data(), count};
364 _PW_SPAN_ASSERT(count <= size());
365 return {data() + (size() - count), count};
369 size_t offset,
size_t count = dynamic_extent)
const noexcept {
371 _PW_SPAN_ASSERT(offset <= size());
372 _PW_SPAN_ASSERT(count == dynamic_extent || count <= size() - offset);
373 return {data() + offset, count != dynamic_extent ? count : size() - offset};
377 constexpr size_t size()
const noexcept {
return ExtentStorage::size(); }
378 constexpr size_t size_bytes()
const noexcept {
return size() *
sizeof(T); }
379 [[nodiscard]]
constexpr bool empty()
const noexcept {
return size() == 0; }
382 constexpr T& operator[](
size_t idx)
const noexcept {
384 _PW_SPAN_ASSERT(idx < size());
385 return *(data() + idx);
388 constexpr T& front()
const noexcept {
389 static_assert(Extent == dynamic_extent || Extent > 0,
390 "Extent must not be 0");
391 _PW_SPAN_ASSERT(Extent != dynamic_extent || !empty());
395 constexpr T& back()
const noexcept {
396 static_assert(Extent == dynamic_extent || Extent > 0,
397 "Extent must not be 0");
398 _PW_SPAN_ASSERT(Extent != dynamic_extent || !empty());
399 return *(data() + size() - 1);
402 constexpr T* data()
const noexcept {
return data_; }
405 constexpr iterator begin()
const noexcept {
return data_; }
406 constexpr iterator end()
const noexcept {
return data_ + size(); }
408 constexpr reverse_iterator rbegin()
const noexcept {
409 return reverse_iterator(end());
411 constexpr reverse_iterator rend()
const noexcept {
412 return reverse_iterator(begin());
427template <
typename T,
size_t X>
428span<
const std::byte, (X == dynamic_extent ? dynamic_extent :
sizeof(T) * X)>
430 return {
reinterpret_cast<const std::byte*
>(s.data()), s.size_bytes()};
435 typename = std::enable_if_t<!std::is_const<T>::value>>
436span<std::byte, (X == dynamic_extent ? dynamic_extent :
sizeof(T) * X)>
437as_writable_bytes(span<T, X> s)
noexcept {
438 return {
reinterpret_cast<std::byte*
>(s.data()), s.size_bytes()};
444#ifdef __cpp_deduction_guides
446template <
class T, std::
size_t N>
447span(T (&)[N]) -> span<T, N>;
449template <
class T, std::
size_t N>
450span(std::array<T, N>&) -> span<T, N>;
452template <
class T, std::
size_t N>
453span(
const std::array<T, N>&) -> span<const T, N>;
455namespace pw_span_internal {
461using ValueType = std::remove_reference_t<decltype(std::declval<T>()[0])>;
466template <
class Container>
467span(Container&) -> span<pw_span_internal::ValueType<Container>>;
469template <
class Container>
470span(
const Container&) -> span<pw_span_internal::ValueType<const Container>>;
Definition: span_impl.h:143
Definition: span_impl.h:235
The Pigweed namespace.
Definition: alignment.h:27
Definition: span_impl.h:60
Definition: span_impl.h:75
Definition: span_impl.h:84