Files
2025-10-25 03:02:53 +03:00

771 lines
30 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[views.span]
# 23 Containers library [[containers]](./#containers)
## 23.7 Views [[views]](views#span)
### 23.7.2 Contiguous access [[views.contiguous]](views.contiguous#views.span)
#### 23.7.2.2 Class template span [views.span]
#### [23.7.2.2.1](#span.overview) Overview [[span.overview]](span.overview)
[1](#span.overview-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20218)
A span is a view over a contiguous sequence of objects,
the storage of which is owned by some other object[.](#span.overview-1.sentence-1)
[2](#span.overview-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20223)
All member functions of span have constant time complexity[.](#span.overview-2.sentence-1)
[🔗](#lib:span_)
namespace std {template<class ElementType, size_t Extent = dynamic_extent>class span {public:// constants and typesusing element_type = ElementType; using value_type = remove_cv_t<ElementType>; using size_type = size_t; using difference_type = ptrdiff_t; using pointer = element_type*; using const_pointer = const element_type*; using reference = element_type&; using const_reference = const element_type&; using iterator = *implementation-defined*; // see [[span.iterators]](#span.iterators "23.7.2.2.7Iterator support")using const_iterator = std::const_iterator<iterator>; using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::const_iterator<reverse_iterator>; static constexpr size_type extent = Extent; // [[span.cons]](#span.cons "23.7.2.2.2Constructors, copy, and assignment"), constructors, copy, and assignmentconstexpr span() noexcept; template<class It>constexpr explicit(extent != dynamic_extent) span(It first, size_type count); template<class It, class End>constexpr explicit(extent != dynamic_extent) span(It first, End last); template<size_t N>constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept; template<class T, size_t N>constexpr span(array<T, N>& arr) noexcept; template<class T, size_t N>constexpr span(const array<T, N>& arr) noexcept; template<class R>constexpr explicit(extent != dynamic_extent) span(R&& r); constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); constexpr span(const span& other) noexcept = default; template<class OtherElementType, size_t OtherExtent>constexpr explicit(*see below*) span(const span<OtherElementType, OtherExtent>& s) noexcept; constexpr span& operator=(const span& other) noexcept = default; // [[span.sub]](#span.sub "23.7.2.2.4Subviews"), subviewstemplate<size_t Count>constexpr span<element_type, Count> first() const; template<size_t Count>constexpr span<element_type, Count> last() const; template<size_t Offset, size_t Count = dynamic_extent>constexpr span<element_type, *see below*> subspan() const; constexpr span<element_type, dynamic_extent> first(size_type count) const; constexpr span<element_type, dynamic_extent> last(size_type count) const; constexpr span<element_type, dynamic_extent> subspan( size_type offset, size_type count = dynamic_extent) const; // [[span.obs]](#span.obs "23.7.2.2.5Observers"), observersconstexpr size_type size() const noexcept; constexpr size_type size_bytes() const noexcept; constexpr bool empty() const noexcept; // [[span.elem]](#span.elem "23.7.2.2.6Element access"), element accessconstexpr reference operator[](size_type idx) const; constexpr reference at(size_type idx) const; // freestanding-deletedconstexpr reference front() const; constexpr reference back() const; constexpr pointer data() const noexcept; // [[span.iterators]](#span.iterators "23.7.2.2.7Iterator support"), iterator supportconstexpr iterator begin() const noexcept; constexpr iterator end() const noexcept; constexpr const_iterator cbegin() const noexcept { return begin(); }constexpr const_iterator cend() const noexcept { return end(); }constexpr reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }constexpr const_reverse_iterator crend() const noexcept { return rend(); }private: pointer *data_*; // *exposition only* size_type *size_*; // *exposition only*}; template<class It, class EndOrSize> span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>, [*maybe-static-ext*](span.syn#concept:maybe-static-ext "23.7.2.1Header <span> synopsis[span.syn]")<EndOrSize>>; template<class T, size_t N> span(T (&)[N]) -> span<T, N>; template<class T, size_t N> span(array<T, N>&) -> span<T, N>; template<class T, size_t N> span(const array<T, N>&) -> span<const T, N>; template<class R> span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;}
[3](#span.overview-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20322)
span<ElementType, Extent> is
a trivially copyable type ([[basic.types.general]](basic.types.general#term.trivially.copyable.type "6.9.1General"))[.](#span.overview-3.sentence-1)
[4](#span.overview-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20326)
ElementType is required to be
a complete object type that is not an abstract class type[.](#span.overview-4.sentence-1)
[5](#span.overview-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20330)
For a span s,
any operation that invalidates a pointer in
the range [s.data(), s.data() + s.size())
invalidates pointers, iterators, and references to elements of s[.](#span.overview-5.sentence-1)
#### [23.7.2.2.2](#span.cons) Constructors, copy, and assignment [[span.cons]](span.cons)
[🔗](#lib:span,constructor)
`constexpr span() noexcept;
`
[1](#span.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20344)
*Constraints*: Extent == dynamic_extent || Extent == 0 is true[.](#span.cons-1.sentence-1)
[2](#span.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20348)
*Postconditions*: size() == 0 && data() == nullptr[.](#span.cons-2.sentence-1)
[🔗](#lib:span,constructor_)
`template<class It>
constexpr explicit(extent != dynamic_extent) span(It first, size_type count);
`
[3](#span.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20361)
*Constraints*: Let U be remove_reference_t<iter_reference_t<It>>[.](#span.cons-3.sentence-1)
- [(3.1)](#span.cons-3.1)
It satisfies [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14Concept contiguous_­iterator[iterator.concept.contiguous]")[.](#span.cons-3.1.sentence-1)
- [(3.2)](#span.cons-3.2)
is_convertible_v<U(*)[], element_type(*)[]> is true[.](#span.cons-3.2.sentence-1)
[*Note [1](#span.cons-note-1)*:
The intent is to allow only qualification conversions
of the iterator reference type to element_type[.](#span.cons-3.2.sentence-2)
— *end note*]
[4](#span.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20374)
*Preconditions*:
- [(4.1)](#span.cons-4.1)
[first, first + count) is a valid range[.](#span.cons-4.1.sentence-1)
- [(4.2)](#span.cons-4.2)
It models [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14Concept contiguous_­iterator[iterator.concept.contiguous]")[.](#span.cons-4.2.sentence-1)
[5](#span.cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20381)
*Hardened preconditions*: If extent is not equal to dynamic_extent,
then count == extent is true[.](#span.cons-5.sentence-1)
[6](#span.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20386)
*Effects*: Initializes *data_* with to_address(first) and*size_* with count[.](#span.cons-6.sentence-1)
[7](#span.cons-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20391)
*Throws*: Nothing[.](#span.cons-7.sentence-1)
[🔗](#lib:span,constructor__)
`template<class It, class End>
constexpr explicit(extent != dynamic_extent) span(It first, End last);
`
[8](#span.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20403)
*Constraints*: Let U be remove_reference_t<iter_reference_t<It>>[.](#span.cons-8.sentence-1)
- [(8.1)](#span.cons-8.1)
is_convertible_v<U(*)[], element_type(*)[]> is true[.](#span.cons-8.1.sentence-1)
[*Note [2](#span.cons-note-2)*:
The intent is to allow only qualification conversions
of the iterator reference type to element_type[.](#span.cons-8.1.sentence-2)
— *end note*]
- [(8.2)](#span.cons-8.2)
It satisfies [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14Concept contiguous_­iterator[iterator.concept.contiguous]")[.](#span.cons-8.2.sentence-1)
- [(8.3)](#span.cons-8.3)
End satisfies [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<It>[.](#span.cons-8.3.sentence-1)
- [(8.4)](#span.cons-8.4)
is_convertible_v<End, size_t> is false[.](#span.cons-8.4.sentence-1)
[9](#span.cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20418)
*Preconditions*:
- [(9.1)](#span.cons-9.1)
[first, last) is a valid range[.](#span.cons-9.1.sentence-1)
- [(9.2)](#span.cons-9.2)
It models [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14Concept contiguous_­iterator[iterator.concept.contiguous]")[.](#span.cons-9.2.sentence-1)
- [(9.3)](#span.cons-9.3)
End models [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<It>[.](#span.cons-9.3.sentence-1)
[10](#span.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20426)
*Hardened preconditions*: If extent is not equal to dynamic_extent,
then (last - first) == extent is true[.](#span.cons-10.sentence-1)
[11](#span.cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20431)
*Effects*: Initializes *data_* with to_address(first) and*size_* with last - first[.](#span.cons-11.sentence-1)
[12](#span.cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20436)
*Throws*: When and what last - first throws[.](#span.cons-12.sentence-1)
[🔗](#lib:span,constructor___)
`template<size_t N> constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept;
template<class T, size_t N> constexpr span(array<T, N>& arr) noexcept;
template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept;
`
[13](#span.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20449)
*Constraints*: Let U be remove_pointer_t<decltype(std::data(arr))>[.](#span.cons-13.sentence-1)
- [(13.1)](#span.cons-13.1)
extent == dynamic_extent || N == extent is true, and
- [(13.2)](#span.cons-13.2)
is_convertible_v<U(*)[], element_type(*)[]> is true. [*Note [3](#span.cons-note-3)*:
The intent is to allow only qualification conversions
of the array element type to element_type[.](#span.cons-13.2.sentence-2)
— *end note*]
[14](#span.cons-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20461)
*Effects*: Constructs a span that is a view over the supplied array[.](#span.cons-14.sentence-1)
[*Note [4](#span.cons-note-4)*:
type_identity_t affects class template argument deduction[.](#span.cons-14.sentence-2)
— *end note*]
[15](#span.cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20468)
*Postconditions*: size() == N && data() == std::data(arr) is true[.](#span.cons-15.sentence-1)
[🔗](#lib:span,constructor____)
`template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r);
`
[16](#span.cons-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20479)
*Constraints*: Let U be remove_reference_t<ranges::range_reference_t<R>>[.](#span.cons-16.sentence-1)
- [(16.1)](#span.cons-16.1)
R satisfies ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6Other range refinements[range.refinements]") and ranges::[sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")[.](#span.cons-16.1.sentence-1)
- [(16.2)](#span.cons-16.2)
Either R satisfies ranges::[borrowed_range](range.range#concept:borrowed_range "25.4.2Ranges[range.range]") oris_const_v<element_type> is true[.](#span.cons-16.2.sentence-1)
- [(16.3)](#span.cons-16.3)
remove_cvref_t<R> is not a specialization of span[.](#span.cons-16.3.sentence-1)
- [(16.4)](#span.cons-16.4)
remove_cvref_t<R> is not a specialization of array[.](#span.cons-16.4.sentence-1)
- [(16.5)](#span.cons-16.5)
is_array_v<remove_cvref_t<R>> is false[.](#span.cons-16.5.sentence-1)
- [(16.6)](#span.cons-16.6)
is_convertible_v<U(*)[], element_type(*)[]> is true[.](#span.cons-16.6.sentence-1)
[*Note [5](#span.cons-note-5)*:
The intent is to allow only qualification conversions
of the range reference type to element_type[.](#span.cons-16.6.sentence-2)
— *end note*]
[17](#span.cons-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20498)
*Preconditions*:
- [(17.1)](#span.cons-17.1)
R models ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6Other range refinements[range.refinements]") andranges::[sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")[.](#span.cons-17.1.sentence-1)
- [(17.2)](#span.cons-17.2)
If is_const_v<element_type> is false,R models ranges::[borrowed_range](range.range#concept:borrowed_range "25.4.2Ranges[range.range]")[.](#span.cons-17.2.sentence-1)
[18](#span.cons-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20507)
*Hardened preconditions*: If extent is not equal to dynamic_extent,
then ranges::size(r) == extent is true[.](#span.cons-18.sentence-1)
[19](#span.cons-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20512)
*Effects*: Initializes *data_* with ranges::data(r) and*size_* with ranges::size(r)[.](#span.cons-19.sentence-1)
[20](#span.cons-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20517)
*Throws*: What and when ranges::data(r) and ranges::size(r) throw[.](#span.cons-20.sentence-1)
[🔗](#lib:span,constructor_____)
`constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il);
`
[21](#span.cons-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20528)
*Constraints*: is_const_v<element_type> is true[.](#span.cons-21.sentence-1)
[22](#span.cons-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20532)
*Hardened preconditions*: If extent is not equal to dynamic_extent,
then il.size() == extent is true[.](#span.cons-22.sentence-1)
[23](#span.cons-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20537)
*Effects*: Initializes *data_* with il.begin() and*size_* with il.size()[.](#span.cons-23.sentence-1)
[🔗](#lib:span,constructor______)
`constexpr span(const span& other) noexcept = default;
`
[24](#span.cons-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20549)
*Postconditions*: other.size() == size() && other.data() == data()[.](#span.cons-24.sentence-1)
[🔗](#lib:span,constructor_______)
`template<class OtherElementType, size_t OtherExtent>
constexpr explicit(see below) span(const span<OtherElementType, OtherExtent>& s) noexcept;
`
[25](#span.cons-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20561)
*Constraints*:
- [(25.1)](#span.cons-25.1)
extent == dynamic_extent || OtherExtent == dynamic_extent || extent == OtherExtent is true, and
- [(25.2)](#span.cons-25.2)
is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true[.](#span.cons-25.sentence-1)
[*Note [6](#span.cons-note-6)*:
The intent is to allow only qualification conversions
of the OtherElementType to element_type[.](#span.cons-25.2.sentence-2)
— *end note*]
[26](#span.cons-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20572)
*Hardened preconditions*: If extent is not equal to dynamic_extent,
then s.size() == extent is true[.](#span.cons-26.sentence-1)
[27](#span.cons-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20577)
*Effects*: Constructs a span that is a view over the range
[s.data(), s.data() + s.size())[.](#span.cons-27.sentence-1)
[28](#span.cons-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20582)
*Postconditions*: size() == s.size() && data() == s.data()[.](#span.cons-28.sentence-1)
[29](#span.cons-29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20586)
*Remarks*: The expression inside explicit is equivalent to:extent != dynamic_extent && OtherExtent == dynamic_extent
[🔗](#lib:operator=,span)
`constexpr span& operator=(const span& other) noexcept = default;
`
[30](#span.cons-30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20600)
*Postconditions*: size() == other.size() && data() == other.data()[.](#span.cons-30.sentence-1)
#### [23.7.2.2.3](#span.deduct) Deduction guides [[span.deduct]](span.deduct)
[🔗](#lib:span,deduction_guide)
`template<class It, class EndOrSize>
span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>,
[maybe-static-ext](span.syn#concept:maybe-static-ext "23.7.2.1Header <span> synopsis[span.syn]")<EndOrSize>>;
`
[1](#span.deduct-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20615)
*Constraints*: It satisfies [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14Concept contiguous_­iterator[iterator.concept.contiguous]")[.](#span.deduct-1.sentence-1)
[🔗](#lib:span,deduction_guide_)
`template<class R>
span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
`
[2](#span.deduct-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20627)
*Constraints*: R satisfies ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6Other range refinements[range.refinements]")[.](#span.deduct-2.sentence-1)
#### [23.7.2.2.4](#span.sub) Subviews [[span.sub]](span.sub)
[🔗](#lib:span,first)
`template<size_t Count> constexpr span<element_type, Count> first() const;
`
[1](#span.sub-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20640)
*Mandates*: Count <= Extent is true[.](#span.sub-1.sentence-1)
[2](#span.sub-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20644)
*Hardened preconditions*: Count <= size() is true[.](#span.sub-2.sentence-1)
[3](#span.sub-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20648)
*Effects*: Equivalent to: return R{data(), Count}; where R is the return type[.](#span.sub-3.sentence-1)
[🔗](#lib:span,last)
`template<size_t Count> constexpr span<element_type, Count> last() const;
`
[4](#span.sub-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20660)
*Mandates*: Count <= Extent is true[.](#span.sub-4.sentence-1)
[5](#span.sub-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20664)
*Hardened preconditions*: Count <= size() is true[.](#span.sub-5.sentence-1)
[6](#span.sub-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20668)
*Effects*: Equivalent to: return R{data() + (size() - Count), Count}; where R is the return type[.](#span.sub-6.sentence-1)
[🔗](#lib:span,subspan)
`template<size_t Offset, size_t Count = dynamic_extent>
constexpr span<element_type, see below> subspan() const;
`
[7](#span.sub-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20681)
*Mandates*: Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset) is true[.](#span.sub-7.sentence-1)
[8](#span.sub-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20688)
*Hardened preconditions*: Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset) is true[.](#span.sub-8.sentence-1)
[9](#span.sub-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20695)
*Effects*: Equivalent to:return span<ElementType, *see below*>( data() + Offset, Count != dynamic_extent ? Count : size() - Offset);
[10](#span.sub-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20703)
*Remarks*: The second template argument of the returned span type is:Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : dynamic_extent)
[🔗](#lib:span,first_)
`constexpr span<element_type, dynamic_extent> first(size_type count) const;
`
[11](#span.sub-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20719)
*Hardened preconditions*: count <= size() is true[.](#span.sub-11.sentence-1)
[12](#span.sub-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20723)
*Effects*: Equivalent to: return {data(), count};
[🔗](#lib:span,last_)
`constexpr span<element_type, dynamic_extent> last(size_type count) const;
`
[13](#span.sub-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20734)
*Hardened preconditions*: count <= size() is true[.](#span.sub-13.sentence-1)
[14](#span.sub-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20738)
*Effects*: Equivalent to: return {data() + (size() - count), count};
[🔗](#lib:span,subspan_)
`constexpr span<element_type, dynamic_extent> subspan(
size_type offset, size_type count = dynamic_extent) const;
`
[15](#span.sub-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20750)
*Hardened preconditions*: offset <= size() && (count == dynamic_extent || count <= size() - offset) is true[.](#span.sub-15.sentence-1)
[16](#span.sub-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20757)
*Effects*: Equivalent to:return {data() + offset, count == dynamic_extent ? size() - offset : count};
#### [23.7.2.2.5](#span.obs) Observers [[span.obs]](span.obs)
[🔗](#lib:span,size)
`constexpr size_type size() const noexcept;
`
[1](#span.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20773)
*Effects*: Equivalent to: return *size_*;
[🔗](#lib:span,size_bytes)
`constexpr size_type size_bytes() const noexcept;
`
[2](#span.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20784)
*Effects*: Equivalent to: return size() * sizeof(element_type);
[🔗](#lib:span,empty)
`constexpr bool empty() const noexcept;
`
[3](#span.obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20795)
*Effects*: Equivalent to: return size() == 0;
#### [23.7.2.2.6](#span.elem) Element access [[span.elem]](span.elem)
[🔗](#lib:operator%5b%5d,span)
`constexpr reference operator[](size_type idx) const;
`
[1](#span.elem-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20808)
*Hardened preconditions*: idx < size() is true[.](#span.elem-1.sentence-1)
[2](#span.elem-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20812)
*Returns*: *(data() + idx)[.](#span.elem-2.sentence-1)
[3](#span.elem-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20816)
*Throws*: Nothing[.](#span.elem-3.sentence-1)
[🔗](#lib:span,at)
`constexpr reference at(size_type idx) const;
`
[4](#span.elem-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20827)
*Returns*: *(data() + idx)[.](#span.elem-4.sentence-1)
[5](#span.elem-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20831)
*Throws*: out_of_range if idx >= size() is true[.](#span.elem-5.sentence-1)
[🔗](#lib:span,front)
`constexpr reference front() const;
`
[6](#span.elem-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20842)
*Hardened preconditions*: empty() is false[.](#span.elem-6.sentence-1)
[7](#span.elem-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20846)
*Returns*: *data()[.](#span.elem-7.sentence-1)
[8](#span.elem-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20850)
*Throws*: Nothing[.](#span.elem-8.sentence-1)
[🔗](#lib:span,back)
`constexpr reference back() const;
`
[9](#span.elem-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20861)
*Hardened preconditions*: empty() is false[.](#span.elem-9.sentence-1)
[10](#span.elem-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20865)
*Returns*: *(data() + (size() - 1))[.](#span.elem-10.sentence-1)
[11](#span.elem-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20869)
*Throws*: Nothing[.](#span.elem-11.sentence-1)
[🔗](#lib:span,data)
`constexpr pointer data() const noexcept;
`
[12](#span.elem-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20880)
*Returns*: *data_*[.](#span.elem-12.sentence-1)
#### [23.7.2.2.7](#span.iterators) Iterator support [[span.iterators]](span.iterators)
[🔗](#lib:iterator,span)
`using iterator = implementation-defined;
`
[1](#span.iterators-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20893)
The type
models [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14Concept contiguous_­iterator[iterator.concept.contiguous]") ([[iterator.concept.contiguous]](iterator.concept.contiguous "24.3.4.14Concept contiguous_­iterator")),
meets the *Cpp17RandomAccessIterator* requirements ([[random.access.iterators]](random.access.iterators "24.3.5.7Random access iterators")),
and
meets the requirements for
constexpr iterators ([[iterator.requirements.general]](iterator.requirements.general "24.3.1General")),
whose value type is value_type and
whose reference type is reference[.](#span.iterators-1.sentence-1)
[2](#span.iterators-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20904)
All requirements on container iterators ([[container.reqmts]](container.reqmts "23.2.2.2Container requirements")) apply tospan::iterator as well[.](#span.iterators-2.sentence-1)
[🔗](#lib:span,begin)
`constexpr iterator begin() const noexcept;
`
[3](#span.iterators-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20915)
*Returns*: An iterator referring to the first element in the span[.](#span.iterators-3.sentence-1)
If empty() is true, then it returns the
same value as end()[.](#span.iterators-3.sentence-2)
[🔗](#lib:span,end)
`constexpr iterator end() const noexcept;
`
[4](#span.iterators-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20928)
*Returns*: An iterator which is the past-the-end value[.](#span.iterators-4.sentence-1)
[🔗](#lib:span,rbegin)
`constexpr reverse_iterator rbegin() const noexcept;
`
[5](#span.iterators-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20939)
*Effects*: Equivalent to: return reverse_iterator(end());
[🔗](#lib:span,rend)
`constexpr reverse_iterator rend() const noexcept;
`
[6](#span.iterators-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20950)
*Effects*: Equivalent to: return reverse_iterator(begin());