246template <
typename ElementType, std::
size_t Extent>
class span {
247 static_assert(std::is_object<ElementType>::value,
"A span's ElementType must be an object type (not a "
248 "reference type or void)");
251 static_assert(!std::is_abstract<ElementType>::value,
"A span's ElementType cannot be an abstract class type");
257 using element_type = ElementType;
258 using value_type =
typename std::remove_cv<ElementType>::type;
259 using size_type = std::size_t;
260 using difference_type = std::ptrdiff_t;
261 using pointer = element_type*;
262 using const_pointer =
const element_type*;
263 using reference = element_type&;
264 using const_reference =
const element_type&;
265 using iterator = pointer;
266 using reverse_iterator = std::reverse_iterator<iterator>;
268 static constexpr size_type extent = Extent;
271 template <std::
size_t E = Extent,
typename std::enable_if<(E == dynamic_extent || E <= 0),
int>::type = 0> constexpr span() noexcept {}
273 TCB_SPAN_CONSTEXPR11 span(po
inter ptr,
size_type count)
274 : storage_(ptr, count) {
275 TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent);
278 TCB_SPAN_CONSTEXPR11 span(po
inter first_elem, po
inter last_elem)
279 : storage_(first_elem, last_elem - first_elem) {
280 TCB_SPAN_EXPECT(extent == dynamic_extent || last_elem - first_elem == static_cast<std::ptrdiff_t>(extent));
283 template <std::
size_t N, std::
size_t E = Extent,
284 typename std::enable_if<(E == dynamic_extent || N == E) &&
285 detail::is_container_element_type_compatible<element_type (&)[N], ElementType>::value,
287 constexpr span(element_type (&arr)[N]) noexcept
288 : storage_(arr, N) {}
290 template <
typename T, std::size_t N, std::size_t E = Extent,
291 typename std::enable_if<(E == dynamic_extent || N == E) &&
294 TCB_SPAN_ARRAY_CONSTEXPR span(std::array<T, N>& arr) noexcept
295 : storage_(arr.data(), N) {}
297 template <
typename T, std::size_t N, std::size_t E = Extent,
298 typename std::enable_if<(E == dynamic_extent || N == E) &&
301 TCB_SPAN_ARRAY_CONSTEXPR span(
const std::array<T, N>& arr) noexcept
302 : storage_(arr.data(), N) {}
304 template <
typename Container, std::size_t E = Extent,
305 typename std::enable_if<E == dynamic_extent && detail::is_container<Container>::value &&
308 constexpr span(Container& cont)
309 : storage_(detail::data(cont), detail::size(cont)) {}
311 template <
typename Container, std::size_t E = Extent,
312 typename std::enable_if<E == dynamic_extent && detail::is_container<Container>::value &&
315 constexpr span(
const Container& cont)
316 : storage_(detail::data(cont), detail::size(cont)) {}
318 constexpr span(
const span& other)
noexcept =
default;
320 template <
typename OtherElementType, std::size_t OtherExtent,
321 typename std::enable_if<(Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent) &&
322 std::is_convertible<OtherElementType (*)[], ElementType (*)[]>::value,
324 constexpr span(
const span<OtherElementType, OtherExtent>& other) noexcept
325 : storage_(other.data(), other.size()) {}
327 ~span()
noexcept =
default;
329 TCB_SPAN_CONSTEXPR_ASSIGN span& operator=(
const span& other)
noexcept =
default;
332 template <std::
size_t Count> TCB_SPAN_CONSTEXPR11 span<element_type, Count> first()
const {
333 TCB_SPAN_EXPECT(Count <= size());
334 return {data(), Count};
337 template <std::
size_t Count> TCB_SPAN_CONSTEXPR11 span<element_type, Count> last()
const {
338 TCB_SPAN_EXPECT(Count <= size());
339 return {data() + (size() - Count), Count};
342 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
343 using subspan_return_t =
344 span<ElementType, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : dynamic_extent)>;
346 template <std::
size_t Offset, std::
size_t Count = dynamic_extent> TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan()
const {
347 TCB_SPAN_EXPECT(Offset <= size() && (Count == dynamic_extent || Offset + Count <= size()));
348 return {data() + Offset, Count != dynamic_extent ? Count : size() - Offset};
351 TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> first(size_type count)
const {
352 TCB_SPAN_EXPECT(count <= size());
353 return {data(), count};
356 TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> last(size_type count)
const {
357 TCB_SPAN_EXPECT(count <= size());
358 return {data() + (size() - count), count};
361 TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> subspan(size_type offset, size_type count = dynamic_extent)
const {
362 TCB_SPAN_EXPECT(offset <= size() && (count == dynamic_extent || offset + count <= size()));
363 return {data() + offset, count == dynamic_extent ? size() - offset : count};
367 constexpr size_type size()
const noexcept {
return storage_.size; }
369 constexpr size_type size_bytes()
const noexcept {
return size() *
sizeof(element_type); }
371 TCB_SPAN_NODISCARD
constexpr bool empty()
const noexcept {
return size() == 0; }
374 TCB_SPAN_CONSTEXPR11 reference operator[](size_type idx)
const {
375 TCB_SPAN_EXPECT(idx < size());
376 return *(data() + idx);
379 TCB_SPAN_CONSTEXPR11 reference front()
const {
380 TCB_SPAN_EXPECT(!empty());
384 TCB_SPAN_CONSTEXPR11 reference back()
const {
385 TCB_SPAN_EXPECT(!empty());
386 return *(data() + (size() - 1));
389 constexpr pointer data()
const noexcept {
return storage_.ptr; }
392 constexpr iterator begin()
const noexcept {
return data(); }
394 constexpr iterator end()
const noexcept {
return data() + size(); }
396 TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin()
const noexcept {
return reverse_iterator(end()); }
398 TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend()
const noexcept {
return reverse_iterator(begin()); }
401 storage_type storage_{};