[views] # 23 Containers library [[containers]](./#containers) ## 23.7 Views [views] ### [23.7.1](#general) General [[views.general]](views.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20162) The header [](#header:%3cspan%3e "23.7.2.1 Header synopsis [span.syn]") defines the view span[.](#general-1.sentence-1) The header [](#header:%3cmdspan%3e "23.7.3.2 Header synopsis [mdspan.syn]") defines the class template mdspan and other facilities for interacting with these multidimensional views[.](#general-1.sentence-2) ### [23.7.2](#contiguous) Contiguous access [[views.contiguous]](views.contiguous) #### [23.7.2.1](#span.syn) Header synopsis [[span.syn]](span.syn) [🔗](#header:%3cspan%3e) #include // see [[initializer.list.syn]](initializer.list.syn "17.11.2 Header synopsis")// mostly freestandingnamespace std {// constantsinline constexpr size_t [dynamic_extent](#lib:dynamic_extent "23.7.2.1 Header synopsis [span.syn]") = numeric_limits::max(); templateconcept [*integral-constant-like*](#concept:integral-constant-like "23.7.2.1 Header synopsis [span.syn]") = // *exposition only* is_integral_v> &&!is_same_v> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") &&[equality_comparable_with](concept.equalitycomparable#concept:equality_comparable_with "18.5.4 Concept equality_­comparable [concept.equalitycomparable]") && bool_constant::value && bool_constant(T()) == T::value>::value; templateconstexpr size_t [*maybe-static-ext*](#concept:maybe-static-ext "23.7.2.1 Header synopsis [span.syn]") = dynamic_extent; // *exposition only*template<[*integral-constant-like*](#concept:integral-constant-like "23.7.2.1 Header synopsis [span.syn]") T>constexpr size_t [*maybe-static-ext*](#concept:maybe-static-ext "23.7.2.1 Header synopsis [span.syn]") = {T::value}; // [[views.span]](#span "23.7.2.2 Class template span"), class template spantemplateclass span; // partially freestandingtemplateconstexpr bool ranges::enable_view> = true; templateconstexpr bool ranges::enable_borrowed_range> = true; // [[span.objectrep]](#span.objectrep "23.7.2.3 Views of object representation"), views of object representationtemplate span as_bytes(span s) noexcept; template span as_writable_bytes(span s) noexcept;} #### [23.7.2.2](#span) Class template span [[views.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 {templateclass span {public:// constants and typesusing element_type = ElementType; using value_type = remove_cv_t; 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.7 Iterator support")using const_iterator = std::const_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::const_iterator; static constexpr size_type extent = Extent; // [[span.cons]](#span.cons "23.7.2.2.2 Constructors, copy, and assignment"), constructors, copy, and assignmentconstexpr span() noexcept; templateconstexpr explicit(extent != dynamic_extent) span(It first, size_type count); templateconstexpr explicit(extent != dynamic_extent) span(It first, End last); templateconstexpr span(type_identity_t (&arr)[N]) noexcept; templateconstexpr span(array& arr) noexcept; templateconstexpr span(const array& arr) noexcept; templateconstexpr explicit(extent != dynamic_extent) span(R&& r); constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); constexpr span(const span& other) noexcept = default; templateconstexpr explicit(*see below*) span(const span& s) noexcept; constexpr span& operator=(const span& other) noexcept = default; // [[span.sub]](#span.sub "23.7.2.2.4 Subviews"), subviewstemplateconstexpr span first() const; templateconstexpr span last() const; templateconstexpr span subspan() const; constexpr span first(size_type count) const; constexpr span last(size_type count) const; constexpr span subspan( size_type offset, size_type count = dynamic_extent) const; // [[span.obs]](#span.obs "23.7.2.2.5 Observers"), 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.6 Element 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.7 Iterator 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 span(It, EndOrSize) -> span>, [*maybe-static-ext*](#concept:maybe-static-ext "23.7.2.1 Header synopsis [span.syn]")>; template span(T (&)[N]) -> span; template span(array&) -> span; template span(const array&) -> span; template span(R&&) -> span>>;} [3](#span.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20322) span is a trivially copyable type ([[basic.types.general]](basic.types.general#term.trivially.copyable.type "6.9.1 General"))[.](#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 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>[.](#span.cons-3.sentence-1) - [(3.1)](#span.cons-3.1) It satisfies [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_­iterator [iterator.concept.contiguous]")[.](#span.cons-3.1.sentence-1) - [(3.2)](#span.cons-3.2) is_convertible_v 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.14 Concept 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 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>[.](#span.cons-8.sentence-1) - [(8.1)](#span.cons-8.1) is_convertible_v 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.14 Concept 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.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")[.](#span.cons-8.3.sentence-1) - [(8.4)](#span.cons-8.4) is_convertible_v 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.14 Concept 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.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")[.](#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 constexpr span(type_identity_t (&arr)[N]) noexcept; template constexpr span(array& arr) noexcept; template constexpr span(const array& arr) noexcept; ` [13](#span.cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20449) *Constraints*: Let U be remove_pointer_t[.](#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 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 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>[.](#span.cons-16.sentence-1) - [(16.1)](#span.cons-16.1) R satisfies ranges​::​[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") and ranges​::​[sized_range](range.sized#concept:sized_range "25.4.4 Sized 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.2 Ranges [range.range]") oris_const_v is true[.](#span.cons-16.2.sentence-1) - [(16.3)](#span.cons-16.3) remove_cvref_t is not a specialization of span[.](#span.cons-16.3.sentence-1) - [(16.4)](#span.cons-16.4) remove_cvref_t is not a specialization of array[.](#span.cons-16.4.sentence-1) - [(16.5)](#span.cons-16.5) is_array_v> is false[.](#span.cons-16.5.sentence-1) - [(16.6)](#span.cons-16.6) is_convertible_v 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.6 Other range refinements [range.refinements]") andranges​::​[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")[.](#span.cons-17.1.sentence-1) - [(17.2)](#span.cons-17.2) If is_const_v is false,R models ranges​::​[borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [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 il); ` [21](#span.cons-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20528) *Constraints*: is_const_v 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 constexpr explicit(see below) span(const span& 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 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 span(It, EndOrSize) -> span>, [maybe-static-ext](#concept:maybe-static-ext "23.7.2.1 Header synopsis [span.syn]")>; ` [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.14 Concept contiguous_­iterator [iterator.concept.contiguous]")[.](#span.deduct-1.sentence-1) [🔗](#lib:span,deduction_guide_) `template span(R&&) -> span>>; ` [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.6 Other 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 constexpr span 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 constexpr span 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 constexpr span 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( 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 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 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 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.14 Concept contiguous_­iterator [iterator.concept.contiguous]") ([[iterator.concept.contiguous]](iterator.concept.contiguous "24.3.4.14 Concept contiguous_­iterator")), meets the *Cpp17RandomAccessIterator* requirements ([[random.access.iterators]](random.access.iterators "24.3.5.7 Random access iterators")), and meets the requirements for constexpr iterators ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General")), 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.2 Container 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()); #### [23.7.2.3](#span.objectrep) Views of object representation [[span.objectrep]](span.objectrep) [🔗](#lib:as_bytes) `template span as_bytes(span s) noexcept; ` [1](#span.objectrep-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20965) *Effects*: Equivalent to: return R{reinterpret_cast(s.data()), s.size_bytes()}; where R is the return type[.](#span.objectrep-1.sentence-1) [🔗](#lib:as_writable_bytes) `template span as_writable_bytes(span s) noexcept; ` [2](#span.objectrep-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20979) *Constraints*: is_const_v is false[.](#span.objectrep-2.sentence-1) [3](#span.objectrep-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20983) *Effects*: Equivalent to: return R{reinterpret_cast(s.data()), s.size_bytes()}; where R is the return type[.](#span.objectrep-3.sentence-1) ### [23.7.3](#multidim) Multidimensional access [[views.multidim]](views.multidim) #### [23.7.3.1](#mdspan.overview) Overview [[mdspan.overview]](mdspan.overview) [1](#mdspan.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L20993) A [*multidimensional index space*](#def:index_space,multidimensional "23.7.3.1 Overview [mdspan.overview]") is a Cartesian product of integer intervals[.](#mdspan.overview-1.sentence-1) Each interval can be represented by a half-open range [Li,Ui), where Li and Ui are the lower and upper bounds of the ith dimension[.](#mdspan.overview-1.sentence-2) The [*rank*](#def:rank "23.7.3.1 Overview [mdspan.overview]") of a multidimensional index space is the number of intervals it represents[.](#mdspan.overview-1.sentence-3) The [*size of a multidimensional index space*](#def:size_of_a_multidimensional_index_space "23.7.3.1 Overview [mdspan.overview]") is the product of Ui−Li for each dimension i if its rank is greater than 0, and 1 otherwise[.](#mdspan.overview-1.sentence-4) [2](#mdspan.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21005) An integer r is a [*rank index*](#def:rank_index "23.7.3.1 Overview [mdspan.overview]") of an index space S if r is in the range [0,rank of S)[.](#mdspan.overview-2.sentence-1) [3](#mdspan.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21009) A pack of integers idx is a [*multidimensional index*](#def:index,multidimensional "23.7.3.1 Overview [mdspan.overview]") in a multidimensional index space S (or representation thereof) if both of the following are true: - [(3.1)](#mdspan.overview-3.1) sizeof...(idx) is equal to the rank of S, and - [(3.2)](#mdspan.overview-3.2) for every rank index i of S, the ith value of idx is an integer in the interval [Li,Ui) of S[.](#mdspan.overview-3.sentence-1) #### [23.7.3.2](#mdspan.syn) Header synopsis [[mdspan.syn]](mdspan.syn) [🔗](#header:%3cmdspan%3e) // mostly freestandingnamespace std {// [[mdspan.extents]](#mdspan.extents "23.7.3.3 Class template extents"), class template extentstemplateclass extents; // [[mdspan.extents.dextents]](#mdspan.extents.dextents "23.7.3.3.6 Alias template dextents"), alias template dextentstemplateusing dextents = *see below*; // [[mdspan.extents.dims]](#mdspan.extents.dims "23.7.3.3.7 Alias template dims"), alias template dimstemplateusing dims = *see below*; // [[mdspan.layout]](#mdspan.layout "23.7.3.4 Layout mapping"), layout mappingstruct layout_left; struct layout_right; struct layout_stride; templatestruct layout_left_padded; templatestruct layout_right_padded; // [[mdspan.accessor.default]](#mdspan.accessor.default "23.7.3.5.3 Class template default_­accessor"), class template default_accessortemplateclass default_accessor; // [[mdspan.accessor.aligned]](#mdspan.accessor.aligned "23.7.3.5.4 Class template aligned_­accessor"), class template aligned_accessortemplateclass aligned_accessor; // [[mdspan.mdspan]](#mdspan.mdspan "23.7.3.6 Class template mdspan"), class template mdspantemplate>class mdspan; // partially freestanding// [[mdspan.sub]](#mdspan.sub "23.7.3.7 submdspan"), submdspan creationtemplatestruct strided_slice; templatestruct submdspan_mapping_result; struct full_extent_t { explicit full_extent_t() = default; }; inline constexpr full_extent_t full_extent{}; templateconstexpr auto submdspan_extents(const extents&, SliceSpecifiers...); // [[mdspan.sub.sub]](#mdspan.sub.sub "23.7.3.7.7 submdspan function template"), submdspan function templatetemplateconstexpr auto submdspan(const mdspan& src, SliceSpecifiers... slices) -> *see below*; templateconcept [*index-pair-like*](#concept:index-pair-like "23.7.3.2 Header synopsis [mdspan.syn]") = // *exposition only*[*pair-like*](tuple.syn#concept:pair-like "22.4.2 Header synopsis [tuple.syn]") &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), IndexType> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), IndexType>;} #### [23.7.3.3](#mdspan.extents) Class template extents [[mdspan.extents]](mdspan.extents) #### [23.7.3.3.1](#mdspan.extents.overview) Overview [[mdspan.extents.overview]](mdspan.extents.overview) The class template extents represents a multidimensional index space of rank equal to sizeof...(Extents)[.](#mdspan.extents.overview-sentence-1) In [views],extents is used synonymously with multidimensional index space[.](#mdspan.extents.overview-sentence-2) namespace std {templateclass [extents](#lib:extents "23.7.3.3.1 Overview [mdspan.extents.overview]") {public:using index_type = IndexType; using size_type = make_unsigned_t; using rank_type = size_t; // [[mdspan.extents.obs]](#mdspan.extents.obs "23.7.3.3.4 Observers of the multidimensional index space"), observers of the multidimensional index spacestatic constexpr rank_type rank() noexcept { return sizeof...(Extents); }static constexpr rank_type rank_dynamic() noexcept { return *dynamic-index*(rank()); }static constexpr size_t static_extent(rank_type) noexcept; constexpr index_type extent(rank_type) const noexcept; // [[mdspan.extents.cons]](#mdspan.extents.cons "23.7.3.3.3 Constructors"), constructorsconstexpr extents() noexcept = default; templateconstexpr explicit(*see below*) extents(const extents&) noexcept; templateconstexpr explicit extents(OtherIndexTypes...) noexcept; templateconstexpr explicit(N != rank_dynamic()) extents(span) noexcept; templateconstexpr explicit(N != rank_dynamic()) extents(const array&) noexcept; // [[mdspan.extents.cmp]](#mdspan.extents.cmp "23.7.3.3.5 Comparison operators"), comparison operatorstemplatefriend constexpr bool operator==(const extents&, const extents&) noexcept; // [[mdspan.extents.expo]](#mdspan.extents.expo "23.7.3.3.2 Exposition-only helpers"), exposition-only helpersconstexpr size_t *fwd-prod-of-extents*(rank_type) const noexcept; // *exposition only*constexpr size_t *rev-prod-of-extents*(rank_type) const noexcept; // *exposition only*templatestatic constexpr auto *index-cast*(OtherIndexType&&) noexcept; // *exposition only*private:static constexpr rank_type *dynamic-index*(rank_type) noexcept; // *exposition only*static constexpr rank_type *dynamic-index-inv*(rank_type) noexcept; // *exposition only* array *dynamic-extents*{}; // *exposition only*}; templateexplicit extents(Integrals...)-> *see below*;} [1](#mdspan.extents.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21152) *Mandates*: - [(1.1)](#mdspan.extents.overview-1.1) IndexType is a signed or unsigned integer type, and - [(1.2)](#mdspan.extents.overview-1.2) each element of Extents is either equal to dynamic_extent, or is representable as a value of type IndexType[.](#mdspan.extents.overview-1.sentence-1) [2](#mdspan.extents.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21162) Each specialization of extents models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") and is trivially copyable[.](#mdspan.extents.overview-2.sentence-1) [3](#mdspan.extents.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21166) Let Er be the rth element of Extents[.](#mdspan.extents.overview-3.sentence-1) Er is a [*dynamic extent*](#def:extent,dynamic "23.7.3.3.1 Overview [mdspan.extents.overview]") if it is equal to dynamic_extent, otherwise Er is a [*static extent*](#def:extent,static "23.7.3.3.1 Overview [mdspan.extents.overview]")[.](#mdspan.extents.overview-3.sentence-2) Let Dr be the value of *dynamic-extents*[*dynamic-index*(r)] if Er is a dynamic extent, otherwise Er[.](#mdspan.extents.overview-3.sentence-3) [4](#mdspan.extents.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21174) The rth interval of the multidimensional index space represented by an extents object is [0,Dr)[.](#mdspan.extents.overview-4.sentence-1) #### [23.7.3.3.2](#mdspan.extents.expo) Exposition-only helpers [[mdspan.extents.expo]](mdspan.extents.expo) [🔗](#mdspan.extents.expo-itemdecl:1) `static constexpr rank_type dynamic-index(rank_type i) noexcept; ` [1](#mdspan.extents.expo-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21185) *Preconditions*: i <= rank() is true[.](#mdspan.extents.expo-1.sentence-1) [2](#mdspan.extents.expo-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21189) *Returns*: The number of Er with r 0 is true, the product of extent(k) for all k in the range [0, i), otherwise 1[.](#mdspan.extents.expo-6.sentence-1) [🔗](#mdspan.extents.expo-itemdecl:4) `constexpr size_t rev-prod-of-extents(rank_type i) const noexcept; ` [7](#mdspan.extents.expo-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21230) *Preconditions*: i < rank() is true[.](#mdspan.extents.expo-7.sentence-1) [8](#mdspan.extents.expo-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21234) *Returns*: If i + 1 < rank() is true, the product of extent(k) for all k in the range [i + 1, rank()), otherwise 1[.](#mdspan.extents.expo-8.sentence-1) [🔗](#mdspan.extents.expo-itemdecl:5) `template static constexpr auto index-cast(OtherIndexType&& i) noexcept; ` [9](#mdspan.extents.expo-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21248) *Effects*: - [(9.1)](#mdspan.extents.expo-9.1) If OtherIndexType is an integral type other than bool, then equivalent to return i;, - [(9.2)](#mdspan.extents.expo-9.2) otherwise, equivalent to return static_cast(i);[.](#mdspan.extents.expo-9.sentence-1) [*Note [1](#mdspan.extents.expo-note-1)*: This function will always return an integral type other than bool[.](#mdspan.extents.expo-9.sentence-2) Since this function's call sites are constrained on convertibility of OtherIndexType to index_type, integer-class types can use the static_cast branch without loss of precision[.](#mdspan.extents.expo-9.sentence-3) — *end note*] #### [23.7.3.3.3](#mdspan.extents.cons) Constructors [[mdspan.extents.cons]](mdspan.extents.cons) [🔗](#lib:extents,constructor) `template constexpr explicit(see below) extents(const extents& other) noexcept; ` [1](#mdspan.extents.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21276) *Constraints*: - [(1.1)](#mdspan.extents.cons-1.1) sizeof...(OtherExtents) == rank() is true[.](#mdspan.extents.cons-1.1.sentence-1) - [(1.2)](#mdspan.extents.cons-1.2) ((OtherExtents == dynamic_extent || Extents == dynamic_extent || OtherExtents == Extents) && ...) is true[.](#mdspan.extents.cons-1.2.sentence-1) [2](#mdspan.extents.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21285) *Preconditions*: - [(2.1)](#mdspan.extents.cons-2.1) other.extent(r) equals Er for each r for which Er is a static extent, and - [(2.2)](#mdspan.extents.cons-2.2) either * [(2.2.1)](#mdspan.extents.cons-2.2.1) sizeof...(OtherExtents) is zero, or * [(2.2.2)](#mdspan.extents.cons-2.2.2) other.extent(r) is representable as a value of type index_type for every rank index r of other[.](#mdspan.extents.cons-2.sentence-1) [3](#mdspan.extents.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21302) *Postconditions*: *this == other is true[.](#mdspan.extents.cons-3.sentence-1) [4](#mdspan.extents.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21306) *Remarks*: The expression inside explicit is equivalent to:(((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) ||(numeric_limits::max() < numeric_limits::max()) [🔗](#lib:extents,constructor_) `template constexpr explicit extents(OtherIndexTypes... exts) noexcept; ` [5](#mdspan.extents.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21322) Let N be sizeof...(OtherIndexTypes), and let exts_arr bearray{static_cast< index_type>(std​::​move(exts))...}[.](#mdspan.extents.cons-5.sentence-1) [6](#mdspan.extents.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21327) *Constraints*: - [(6.1)](#mdspan.extents.cons-6.1) (is_convertible_v && ...) is true, - [(6.2)](#mdspan.extents.cons-6.2) (is_nothrow_constructible_v && ...) is true, and - [(6.3)](#mdspan.extents.cons-6.3) N == rank_dynamic() || N == rank() is true[.](#mdspan.extents.cons-6.sentence-1) [*Note [1](#mdspan.extents.cons-note-1)*: One can construct extents from just dynamic extents, which are all the values getting stored, or from all the extents with a precondition[.](#mdspan.extents.cons-6.3.sentence-2) — *end note*] [7](#mdspan.extents.cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21343) *Preconditions*: - [(7.1)](#mdspan.extents.cons-7.1) If N != rank_dynamic() is true,exts_arr[r] equals Er for each r for which Er is a static extent, and - [(7.2)](#mdspan.extents.cons-7.2) either * [(7.2.1)](#mdspan.extents.cons-7.2.1) sizeof...(exts) == 0 is true, or * [(7.2.2)](#mdspan.extents.cons-7.2.2) each element of exts is representable as a nonnegative value of type index_type[.](#mdspan.extents.cons-7.sentence-1) [8](#mdspan.extents.cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21361) *Postconditions*: *this == extents(exts_arr) is true[.](#mdspan.extents.cons-8.sentence-1) [🔗](#lib:extents,constructor__) `template constexpr explicit(N != rank_dynamic()) extents(span exts) noexcept; template constexpr explicit(N != rank_dynamic()) extents(const array& exts) noexcept; ` [9](#mdspan.extents.cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21377) *Constraints*: - [(9.1)](#mdspan.extents.cons-9.1) is_convertible_v is true, - [(9.2)](#mdspan.extents.cons-9.2) is_nothrow_constructible_v is true, and - [(9.3)](#mdspan.extents.cons-9.3) N == rank_dynamic() || N == rank() is true[.](#mdspan.extents.cons-9.sentence-1) [10](#mdspan.extents.cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21388) *Preconditions*: - [(10.1)](#mdspan.extents.cons-10.1) If N != rank_dynamic() is true,exts[r] equals Er for each r for which Er is a static extent, and - [(10.2)](#mdspan.extents.cons-10.2) either * [(10.2.1)](#mdspan.extents.cons-10.2.1) N is zero, or * [(10.2.2)](#mdspan.extents.cons-10.2.2) exts[r] is representable as a nonnegative value of type index_type for every rank index r[.](#mdspan.extents.cons-10.sentence-1) [11](#mdspan.extents.cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21405) *Effects*: - [(11.1)](#mdspan.extents.cons-11.1) If N equals rank_dynamic(), for all d in the range [0, rank_dynamic()), direct-non-list-initializes *dynamic-extents*[d] with as_const(exts[d])[.](#mdspan.extents.cons-11.1.sentence-1) - [(11.2)](#mdspan.extents.cons-11.2) Otherwise, for all d in the range [0, rank_dynamic()), direct-non-list-initializes *dynamic-extents*[d] with as_const(exts[*dynamic-index-inv*(d)])[.](#mdspan.extents.cons-11.2.sentence-1) [🔗](#lib:extents,constructor___) `template explicit extents(Integrals...) -> see below; ` [12](#mdspan.extents.cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21427) *Constraints*: (is_convertible_v && ...) is true[.](#mdspan.extents.cons-12.sentence-1) [13](#mdspan.extents.cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21431) *Remarks*: The deduced type is extents synopsis [span.syn]")...>[.](#mdspan.extents.cons-13.sentence-1) #### [23.7.3.3.4](#mdspan.extents.obs) Observers of the multidimensional index space [[mdspan.extents.obs]](mdspan.extents.obs) [🔗](#lib:static_extent,extents) `static constexpr size_t static_extent(rank_type i) noexcept; ` [1](#mdspan.extents.obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21444) *Preconditions*: i < rank() is true[.](#mdspan.extents.obs-1.sentence-1) [2](#mdspan.extents.obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21448) *Returns*: Ei[.](#mdspan.extents.obs-2.sentence-1) [🔗](#lib:extent,extents) `constexpr index_type extent(rank_type i) const noexcept; ` [3](#mdspan.extents.obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21459) *Preconditions*: i < rank() is true[.](#mdspan.extents.obs-3.sentence-1) [4](#mdspan.extents.obs-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21463) *Returns*: Di[.](#mdspan.extents.obs-4.sentence-1) #### [23.7.3.3.5](#mdspan.extents.cmp) Comparison operators [[mdspan.extents.cmp]](mdspan.extents.cmp) [🔗](#lib:operator==,extents) `template friend constexpr bool operator==(const extents& lhs, const extents& rhs) noexcept; ` [1](#mdspan.extents.cmp-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21478) *Returns*: true if lhs.rank() equals rhs.rank() and if lhs.extent(r) equals rhs.extent(r) for every rank index r of rhs, otherwise false[.](#mdspan.extents.cmp-1.sentence-1) #### [23.7.3.3.6](#mdspan.extents.dextents) Alias template dextents [[mdspan.extents.dextents]](mdspan.extents.dextents) [🔗](#lib:dextents) `template using dextents = see below; ` [1](#mdspan.extents.dextents-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21495) *Result*: A type E that is a specialization of extents such that E​::​rank() == Rank && E​::​rank() == E​::​rank_dynamic() is true, andE​::​index_type denotes IndexType[.](#mdspan.extents.dextents-1.sentence-1) #### [23.7.3.3.7](#mdspan.extents.dims) Alias template dims [[mdspan.extents.dims]](mdspan.extents.dims) [🔗](#lib:dims) `template using dims = see below; ` [1](#mdspan.extents.dims-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21511) *Result*: A type E that is a specialization of extents such that E​::​rank() == Rank && E​::​rank() == E​::​rank_dynamic() is true, andE​::​index_type denotes IndexType[.](#mdspan.extents.dims-1.sentence-1) #### [23.7.3.4](#mdspan.layout) Layout mapping [[mdspan.layout]](mdspan.layout) #### [23.7.3.4.1](#mdspan.layout.general) General [[mdspan.layout.general]](mdspan.layout.general) [1](#mdspan.layout.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21522) In [[mdspan.layout.reqmts]](#mdspan.layout.reqmts "23.7.3.4.2 Requirements") and [[mdspan.layout.policy.reqmts]](#mdspan.layout.policy.reqmts "23.7.3.4.3 Layout mapping policy requirements"): - [(1.1)](#mdspan.layout.general-1.1) M denotes a layout mapping class[.](#mdspan.layout.general-1.1.sentence-1) - [(1.2)](#mdspan.layout.general-1.2) m denotes a (possibly const) value of type M[.](#mdspan.layout.general-1.2.sentence-1) - [(1.3)](#mdspan.layout.general-1.3) i and j are packs of (possibly const) integers that are multidimensional indices in m.extents() ([[mdspan.overview]](#mdspan.overview "23.7.3.1 Overview"))[.](#mdspan.layout.general-1.3.sentence-1) [*Note [1](#mdspan.layout.general-note-1)*: The type of each element of the packs can be a different integer type[.](#mdspan.layout.general-1.3.sentence-2) — *end note*] - [(1.4)](#mdspan.layout.general-1.4) r is a (possibly const) rank index of typename M​::​extents_type[.](#mdspan.layout.general-1.4.sentence-1) - [(1.5)](#mdspan.layout.general-1.5) dr is a pack of (possibly const) integers for which sizeof...(dr) == M​::​extents_type​::​rank() is true, the rth element is equal to 1, and all other elements are equal to 0[.](#mdspan.layout.general-1.5.sentence-1) [2](#mdspan.layout.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21549) In [[mdspan.layout.reqmts]](#mdspan.layout.reqmts "23.7.3.4.2 Requirements") through [[mdspan.layout.stride]](#mdspan.layout.stride "23.7.3.4.7 Class template layout_­stride​::​mapping"): - [(2.1)](#mdspan.layout.general-2.1) Let *is-mapping-of* be the exposition-only variable template defined as follows:templateconstexpr bool *is-mapping-of* = // *exposition only* is_same_v, Mapping>; - [(2.2)](#mdspan.layout.general-2.2) Let *is-layout-left-padded-mapping-of* be the exposition-only variable template defined as follows:templateconstexpr bool *is-layout-left-padded-mapping-of* = *see below*; // *exposition only* where *is-layout-left-padded-mapping-of* is true if and only if Mapping denotes a specialization of layout_left_padded​::​mapping for some value S of type size_t. - [(2.3)](#mdspan.layout.general-2.3) Let *is-layout-right-padded-mapping-of* be the exposition-only variable template defined as follows:templateconstexpr bool *is-layout-right-padded-mapping-of* = *see below*; // *exposition only* where *is-layout-right-padded-mapping-of* is true if and only if Mapping denotes a specialization of layout_right_padded​::​mapping for some value S of type size_t. - [(2.4)](#mdspan.layout.general-2.4) For nonnegative integers x and y, let LEAST-MULTIPLE-AT-LEAST(x,y) denote * [(2.4.1)](#mdspan.layout.general-2.4.1) y if x is zero, * [(2.4.2)](#mdspan.layout.general-2.4.2) otherwise, the least multiple of x that is greater than or equal to y. #### [23.7.3.4.2](#mdspan.layout.reqmts) Requirements [[mdspan.layout.reqmts]](mdspan.layout.reqmts) [1](#mdspan.layout.reqmts-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21594) A type M meets the [*layout mapping*](#def:layout_mapping "23.7.3.4.2 Requirements [mdspan.layout.reqmts]") requirements if - [(1.1)](#mdspan.layout.reqmts-1.1) M models [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]") and [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]"), - [(1.2)](#mdspan.layout.reqmts-1.2) is_nothrow_move_constructible_v is true, - [(1.3)](#mdspan.layout.reqmts-1.3) is_nothrow_move_assignable_v is true, - [(1.4)](#mdspan.layout.reqmts-1.4) is_nothrow_swappable_v is true, and - [(1.5)](#mdspan.layout.reqmts-1.5) the following types and expressions are well-formed and have the specified semantics. [🔗](#mdspan.layout.reqmts-itemdecl:1) `typename M::extents_type ` [2](#mdspan.layout.reqmts-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21616) *Result*: A type that is a specialization of extents[.](#mdspan.layout.reqmts-2.sentence-1) [🔗](#mdspan.layout.reqmts-itemdecl:2) `typename M::index_type ` [3](#mdspan.layout.reqmts-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21626) *Result*: typename M​::​extents_type​::​index_type[.](#mdspan.layout.reqmts-3.sentence-1) [🔗](#mdspan.layout.reqmts-itemdecl:3) `typename M::rank_type ` [4](#mdspan.layout.reqmts-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21636) *Result*: typename M​::​extents_type​::​rank_type[.](#mdspan.layout.reqmts-4.sentence-1) [🔗](#mdspan.layout.reqmts-itemdecl:4) `typename M::layout_type ` [5](#mdspan.layout.reqmts-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21646) *Result*: A type MP that meets the layout mapping policy requirements ([[mdspan.layout.policy.reqmts]](#mdspan.layout.policy.reqmts "23.7.3.4.3 Layout mapping policy requirements")) and for which *is-mapping-of* is true[.](#mdspan.layout.reqmts-5.sentence-1) [🔗](#mdspan.layout.reqmts-itemdecl:5) `m.extents() ` [6](#mdspan.layout.reqmts-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21658) *Result*: const typename M​::​extents_type& [🔗](#mdspan.layout.reqmts-itemdecl:6) `m(i...) ` [7](#mdspan.layout.reqmts-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21668) *Result*: typename M​::​index_type [8](#mdspan.layout.reqmts-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21672) *Returns*: A nonnegative integer less than numeric_limits​::​max() and less than or equal to numeric_limits​::​max()[.](#mdspan.layout.reqmts-8.sentence-1) [🔗](#mdspan.layout.reqmts-itemdecl:7) `m(i...) == m(static_cast(i)...) ` [9](#mdspan.layout.reqmts-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21684) *Result*: bool [10](#mdspan.layout.reqmts-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21688) *Returns*: true [🔗](#mdspan.layout.reqmts-itemdecl:8) `m.required_span_size() ` [11](#mdspan.layout.reqmts-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21698) *Result*: typename M​::​index_type [12](#mdspan.layout.reqmts-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21702) *Returns*: If the size of the multidimensional index space m.extents() is 0, then 0, else 1 plus the maximum value of m(i...) for all i[.](#mdspan.layout.reqmts-12.sentence-1) [🔗](#mdspan.layout.reqmts-itemdecl:9) `m.is_unique() ` [13](#mdspan.layout.reqmts-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21714) *Result*: bool [14](#mdspan.layout.reqmts-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21718) *Returns*: true only if for every i and j where (i != j || ...) is true,m(i...) != m(j...) is true[.](#mdspan.layout.reqmts-14.sentence-1) [*Note [1](#mdspan.layout.reqmts-note-1)*: A mapping can return false even if the condition is met[.](#mdspan.layout.reqmts-14.sentence-2) For certain layouts, it is possibly not feasible to determine efficiently whether the layout is unique[.](#mdspan.layout.reqmts-14.sentence-3) — *end note*] [🔗](#mdspan.layout.reqmts-itemdecl:10) `m.is_exhaustive() ` [15](#mdspan.layout.reqmts-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21735) *Result*: bool [16](#mdspan.layout.reqmts-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21739) *Returns*: true only if for all k in the range [0, m.required_span_size()) there exists an i such that m(i...) equals k[.](#mdspan.layout.reqmts-16.sentence-1) [*Note [2](#mdspan.layout.reqmts-note-2)*: A mapping can return false even if the condition is met[.](#mdspan.layout.reqmts-16.sentence-2) For certain layouts, it is possibly not feasible to determine efficiently whether the layout is exhaustive[.](#mdspan.layout.reqmts-16.sentence-3) — *end note*] [🔗](#mdspan.layout.reqmts-itemdecl:11) `m.is_strided() ` [17](#mdspan.layout.reqmts-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21756) *Result*: bool [18](#mdspan.layout.reqmts-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21760) *Returns*: true only if for every rank index r of m.extents() there exists an integer sr such that, for all i where (i+dr) is a multidimensional index in m.extents() ([[mdspan.overview]](#mdspan.overview "23.7.3.1 Overview")),m((i + dr)...) - m(i...) equals sr[.](#mdspan.layout.reqmts-18.sentence-1) [*Note [3](#mdspan.layout.reqmts-note-3)*: This implies that for a strided layoutm(i0,…,ik)=m(0,…,0)+i0×s0+⋯+ik×sk[.](#mdspan.layout.reqmts-18.sentence-2) — *end note*] [*Note [4](#mdspan.layout.reqmts-note-4)*: A mapping can return false even if the condition is met[.](#mdspan.layout.reqmts-18.sentence-3) For certain layouts, it is possibly not feasible to determine efficiently whether the layout is strided[.](#mdspan.layout.reqmts-18.sentence-4) — *end note*] [🔗](#mdspan.layout.reqmts-itemdecl:12) `m.stride(r) ` [19](#mdspan.layout.reqmts-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21784) *Preconditions*: m.is_strided() is true[.](#mdspan.layout.reqmts-19.sentence-1) [20](#mdspan.layout.reqmts-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21788) *Result*: typename M​::​index_type [21](#mdspan.layout.reqmts-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21792) *Returns*: sr as defined in m.is_strided() above[.](#mdspan.layout.reqmts-21.sentence-1) [22](#mdspan.layout.reqmts-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21796) [*Note [5](#mdspan.layout.reqmts-note-5)*: It is not required for m.stride(r) to be well-formed if m.extents().rank() is zero, even if m.is_always_strided() is true[.](#mdspan.layout.reqmts-22.sentence-1) — *end note*] [🔗](#mdspan.layout.reqmts-itemdecl:13) `M::is_always_unique() ` [23](#mdspan.layout.reqmts-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21809) *Result*: A constant expression ([[expr.const]](expr.const "7.7 Constant expressions")) of type bool[.](#mdspan.layout.reqmts-23.sentence-1) [24](#mdspan.layout.reqmts-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21813) *Returns*: true only if m.is_unique() is true for all possible objects m of type M[.](#mdspan.layout.reqmts-24.sentence-1) [*Note [6](#mdspan.layout.reqmts-note-6)*: A mapping can return false even if the above condition is met[.](#mdspan.layout.reqmts-24.sentence-2) For certain layout mappings, it is possibly not feasible to determine whether every instance is unique[.](#mdspan.layout.reqmts-24.sentence-3) — *end note*] [🔗](#mdspan.layout.reqmts-itemdecl:14) `M::is_always_exhaustive() ` [25](#mdspan.layout.reqmts-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21829) *Result*: A constant expression ([[expr.const]](expr.const "7.7 Constant expressions")) of type bool[.](#mdspan.layout.reqmts-25.sentence-1) [26](#mdspan.layout.reqmts-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21833) *Returns*: true only if m.is_exhaustive() is true for all possible objects m of type M[.](#mdspan.layout.reqmts-26.sentence-1) [*Note [7](#mdspan.layout.reqmts-note-7)*: A mapping can return false even if the above condition is met[.](#mdspan.layout.reqmts-26.sentence-2) For certain layout mappings, it is possibly not feasible to determine whether every instance is exhaustive[.](#mdspan.layout.reqmts-26.sentence-3) — *end note*] [🔗](#mdspan.layout.reqmts-itemdecl:15) `M::is_always_strided() ` [27](#mdspan.layout.reqmts-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21849) *Result*: A constant expression ([[expr.const]](expr.const "7.7 Constant expressions")) of type bool[.](#mdspan.layout.reqmts-27.sentence-1) [28](#mdspan.layout.reqmts-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21853) *Returns*: true only if m.is_strided() is true for all possible objects m of type M[.](#mdspan.layout.reqmts-28.sentence-1) [*Note [8](#mdspan.layout.reqmts-note-8)*: A mapping can return false even if the above condition is met[.](#mdspan.layout.reqmts-28.sentence-2) For certain layout mappings, it is possibly not feasible to determine whether every instance is strided[.](#mdspan.layout.reqmts-28.sentence-3) — *end note*] #### [23.7.3.4.3](#mdspan.layout.policy.reqmts) Layout mapping policy requirements [[mdspan.layout.policy.reqmts]](mdspan.layout.policy.reqmts) [1](#mdspan.layout.policy.reqmts-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21866) A type MP meets the [*layout mapping policy*](#def:layout_mapping_policy "23.7.3.4.3 Layout mapping policy requirements [mdspan.layout.policy.reqmts]") requirements if for a type E that is a specialization of extents,MP​::​mapping is valid and denotes a type X that meets the layout mapping requirements ([[mdspan.layout.reqmts]](#mdspan.layout.reqmts "23.7.3.4.2 Requirements")), and for which the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") X​::​layout_type is valid and denotes the type MP and the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") X​::​extents_type denotes E[.](#mdspan.layout.policy.reqmts-1.sentence-1) #### [23.7.3.4.4](#mdspan.layout.policy.overview) Layout mapping policies [[mdspan.layout.policy.overview]](mdspan.layout.policy.overview) namespace std {struct layout_left {templateclass mapping; }; struct layout_right {templateclass mapping; }; struct layout_stride {templateclass mapping; }; templatestruct layout_left_padded {template class mapping; }; templatestruct layout_right_padded {template class mapping; };} [1](#mdspan.layout.policy.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21903) Each of layout_left, layout_right, and layout_stride, as well as each specialization oflayout_left_padded and layout_right_padded, meets the layout mapping policy requirements and is a trivially copyable type[.](#mdspan.layout.policy.overview-1.sentence-1) Furthermore,is_trivially_default_constructible_v is true for any such type T[.](#mdspan.layout.policy.overview-1.sentence-2) #### [23.7.3.4.5](#mdspan.layout.left) Class template layout_left​::​mapping [[mdspan.layout.left]](mdspan.layout.left) #### [23.7.3.4.5.1](#mdspan.layout.left.overview) Overview [[mdspan.layout.left.overview]](mdspan.layout.left.overview) [1](#mdspan.layout.left.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21916) layout_left provides a layout mapping where the leftmost extent has stride 1, and strides increase left-to-right as the product of extents[.](#mdspan.layout.left.overview-1.sentence-1) namespace std {templateclass layout_left::mapping {public:using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_left; // [[mdspan.layout.left.cons]](#mdspan.layout.left.cons "23.7.3.4.5.2 Constructors"), constructorsconstexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; templateconstexpr explicit(!is_convertible_v) mapping(const mapping&) noexcept; templateconstexpr explicit(!is_convertible_v) mapping(const layout_right::mapping&) noexcept; templateconstexpr explicit(!is_convertible_v) mapping(const LayoutLeftPaddedMapping&) noexcept; templateconstexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping&); constexpr mapping& operator=(const mapping&) noexcept = default; // [[mdspan.layout.left.obs]](#mdspan.layout.left.obs "23.7.3.4.5.3 Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const noexcept; templateconstexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; }static constexpr bool is_always_exhaustive() noexcept { return true; }static constexpr bool is_always_strided() noexcept { return true; }static constexpr bool is_unique() noexcept { return true; }static constexpr bool is_exhaustive() noexcept { return true; }static constexpr bool is_strided() noexcept { return true; }constexpr index_type stride(rank_type) const noexcept; templatefriend constexpr bool operator==(const mapping&, const mapping&) noexcept; private: extents_type *extents_*{}; // *exposition only*// [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6 Specializations of submdspan_­mapping"), submdspan mapping specializationtemplateconstexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; templatefriend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {return src.*submdspan-mapping-impl*(slices...); }};} [2](#mdspan.layout.left.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21990) If Extents is not a specialization of extents, then the program is ill-formed[.](#mdspan.layout.left.overview-2.sentence-1) [3](#mdspan.layout.left.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21994) layout_left​::​mapping is a trivially copyable type that models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") for each E[.](#mdspan.layout.left.overview-3.sentence-1) [4](#mdspan.layout.left.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21998) *Mandates*: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type typename Extents​::​index_type[.](#mdspan.layout.left.overview-4.sentence-1) #### [23.7.3.4.5.2](#mdspan.layout.left.cons) Constructors [[mdspan.layout.left.cons]](mdspan.layout.left.cons) [🔗](#lib:layout_left::mapping,constructor) `constexpr mapping(const extents_type& e) noexcept; ` [1](#mdspan.layout.left.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22012) *Preconditions*: The size of the multidimensional index space e is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.left.cons-1.sentence-1) [2](#mdspan.layout.left.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22017) *Effects*: Direct-non-list-initializes *extents_* with e[.](#mdspan.layout.left.cons-2.sentence-1) [🔗](#lib:layout_left::mapping,constructor_) `template constexpr explicit(!is_convertible_v) mapping(const mapping& other) noexcept; ` [3](#mdspan.layout.left.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22030) *Constraints*: is_constructible_v is true[.](#mdspan.layout.left.cons-3.sentence-1) [4](#mdspan.layout.left.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22034) *Preconditions*: other.required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.left.cons-4.sentence-1) [5](#mdspan.layout.left.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22039) *Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#mdspan.layout.left.cons-5.sentence-1) [🔗](#lib:layout_left::mapping,constructor__) `template constexpr explicit(!is_convertible_v) mapping(const layout_right::mapping& other) noexcept; ` [6](#mdspan.layout.left.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22052) *Constraints*: - [(6.1)](#mdspan.layout.left.cons-6.1) extents_type​::​rank() <= 1 is true, and - [(6.2)](#mdspan.layout.left.cons-6.2) is_constructible_v is true[.](#mdspan.layout.left.cons-6.sentence-1) [7](#mdspan.layout.left.cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22061) *Preconditions*: other.required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.left.cons-7.sentence-1) [8](#mdspan.layout.left.cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22066) *Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#mdspan.layout.left.cons-8.sentence-1) [🔗](#lib:layout_left::mapping,constructor___) `template constexpr explicit(!is_convertible_v) mapping(const LayoutLeftPaddedMapping&) noexcept; ` [9](#mdspan.layout.left.cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22080) *Constraints*: - [(9.1)](#mdspan.layout.left.cons-9.1) *is-layout-left-padded-mapping-of* is true[.](#mdspan.layout.left.cons-9.1.sentence-1) - [(9.2)](#mdspan.layout.left.cons-9.2) is_constructible_v is true[.](#mdspan.layout.left.cons-9.2.sentence-1) [10](#mdspan.layout.left.cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22089) *Mandates*: If - [(10.1)](#mdspan.layout.left.cons-10.1) Extents​::​rank() is greater than one, - [(10.2)](#mdspan.layout.left.cons-10.2) Extents​::​static_extent(0) does not equal dynamic_extent, and - [(10.3)](#mdspan.layout.left.cons-10.3) LayoutLeftPaddedMapping​::​*static-padding-stride* does not equal dynamic_extent, then Extents​::​static_extent(0) equalsLayoutLeftPaddedMapping​::​*static-padding-stride*[.](#mdspan.layout.left.cons-10.sentence-1) [11](#mdspan.layout.left.cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22104) *Preconditions*: - [(11.1)](#mdspan.layout.left.cons-11.1) If extents_type​::​rank() > 1 is true, then other.stride(1) equals other.extents(0)[.](#mdspan.layout.left.cons-11.1.sentence-1) - [(11.2)](#mdspan.layout.left.cons-11.2) other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.left.cons-11.2.sentence-1) [12](#mdspan.layout.left.cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22115) *Effects*: Direct-non-list-initializes extents_ with other.extents()[.](#mdspan.layout.left.cons-12.sentence-1) [🔗](#lib:layout_left::mapping,constructor____) `template constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping& other); ` [13](#mdspan.layout.left.cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22128) *Constraints*: is_constructible_v is true[.](#mdspan.layout.left.cons-13.sentence-1) [14](#mdspan.layout.left.cons-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22132) *Preconditions*: - [(14.1)](#mdspan.layout.left.cons-14.1) If extents_type​::​rank() > 0 is true, then for all r in the range [0, extents_type​::​rank()),other.stride(r) equalsother.extents().*fwd-prod-of-extents*(r), and - [(14.2)](#mdspan.layout.left.cons-14.2) other.required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.left.cons-14.sentence-1) [15](#mdspan.layout.left.cons-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22145) *Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#mdspan.layout.left.cons-15.sentence-1) #### [23.7.3.4.5.3](#mdspan.layout.left.obs) Observers [[mdspan.layout.left.obs]](mdspan.layout.left.obs) [🔗](#lib:required_span_size,layout_left::mapping) `constexpr index_type required_span_size() const noexcept; ` [1](#mdspan.layout.left.obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22158) *Returns*: extents().*fwd-prod-of-extents*(extents_type​::​rank())[.](#mdspan.layout.left.obs-1.sentence-1) [🔗](#lib:operator(),layout_left::mapping) `template constexpr index_type operator()(Indices... i) const noexcept; ` [2](#mdspan.layout.left.obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22170) *Constraints*: - [(2.1)](#mdspan.layout.left.obs-2.1) sizeof...(Indices) == extents_type​::​rank() is true, - [(2.2)](#mdspan.layout.left.obs-2.2) (is_convertible_v && ...) is true, and - [(2.3)](#mdspan.layout.left.obs-2.3) (is_nothrow_constructible_v && ...) is true[.](#mdspan.layout.left.obs-2.sentence-1) [3](#mdspan.layout.left.obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22181) *Preconditions*: extents_type​::​*index-cast*(i) is a multidimensional index in *extents_* ([[mdspan.overview]](#mdspan.overview "23.7.3.1 Overview"))[.](#mdspan.layout.left.obs-3.sentence-1) [4](#mdspan.layout.left.obs-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22186) *Effects*: Let P be a parameter pack such thatis_same_v, index_sequence> is true[.](#mdspan.layout.left.obs-4.sentence-1) Equivalent to:return ((static_cast(i) * stride(P)) + ... + 0); [🔗](#lib:stride,layout_left::mapping) `constexpr index_type stride(rank_type i) const noexcept; ` [5](#mdspan.layout.left.obs-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22205) *Constraints*: extents_type​::​rank() > 0 is true[.](#mdspan.layout.left.obs-5.sentence-1) [6](#mdspan.layout.left.obs-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22209) *Preconditions*: i < extents_type​::​rank() is true[.](#mdspan.layout.left.obs-6.sentence-1) [7](#mdspan.layout.left.obs-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22213) *Returns*: extents().*fwd-prod-of-extents*(i)[.](#mdspan.layout.left.obs-7.sentence-1) [🔗](#lib:operator==,layout_left::mapping) `template friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; ` [8](#mdspan.layout.left.obs-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22225) *Constraints*: extents_type​::​rank() == OtherExtents​::​rank() is true[.](#mdspan.layout.left.obs-8.sentence-1) [9](#mdspan.layout.left.obs-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22229) *Effects*: Equivalent to: return x.extents() == y.extents(); #### [23.7.3.4.6](#mdspan.layout.right) Class template layout_right​::​mapping [[mdspan.layout.right]](mdspan.layout.right) #### [23.7.3.4.6.1](#mdspan.layout.right.overview) Overview [[mdspan.layout.right.overview]](mdspan.layout.right.overview) [1](#mdspan.layout.right.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22238) layout_right provides a layout mapping where the rightmost extent is stride 1, and strides increase right-to-left as the product of extents[.](#mdspan.layout.right.overview-1.sentence-1) namespace std {templateclass layout_right::mapping {public:using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_right; // [[mdspan.layout.right.cons]](#mdspan.layout.right.cons "23.7.3.4.6.2 Constructors"), constructorsconstexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; templateconstexpr explicit(!is_convertible_v) mapping(const mapping&) noexcept; templateconstexpr explicit(!is_convertible_v) mapping(const layout_left::mapping&) noexcept; templateconstexpr explicit(!is_convertible_v) mapping(const LayoutRightPaddedMapping&) noexcept; templateconstexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [[mdspan.layout.right.obs]](#mdspan.layout.right.obs "23.7.3.4.6.3 Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const noexcept; templateconstexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; }static constexpr bool is_always_exhaustive() noexcept { return true; }static constexpr bool is_always_strided() noexcept { return true; }static constexpr bool is_unique() noexcept { return true; }static constexpr bool is_exhaustive() noexcept { return true; }static constexpr bool is_strided() noexcept { return true; }constexpr index_type stride(rank_type) const noexcept; templatefriend constexpr bool operator==(const mapping&, const mapping&) noexcept; private: extents_type *extents_*{}; // *exposition only*// [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6 Specializations of submdspan_­mapping"), submdspan mapping specializationtemplateconstexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; templatefriend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {return src.*submdspan-mapping-impl*(slices...); }};} [2](#mdspan.layout.right.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22312) If Extents is not a specialization of extents, then the program is ill-formed[.](#mdspan.layout.right.overview-2.sentence-1) [3](#mdspan.layout.right.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22316) layout_right​::​mapping is a trivially copyable type that models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") for each E[.](#mdspan.layout.right.overview-3.sentence-1) [4](#mdspan.layout.right.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22320) *Mandates*: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type typename Extents​::​index_type[.](#mdspan.layout.right.overview-4.sentence-1) #### [23.7.3.4.6.2](#mdspan.layout.right.cons) Constructors [[mdspan.layout.right.cons]](mdspan.layout.right.cons) [🔗](#lib:layout_right::mapping,constructor) `constexpr mapping(const extents_type& e) noexcept; ` [1](#mdspan.layout.right.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22334) *Preconditions*: The size of the multidimensional index space e is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.right.cons-1.sentence-1) [2](#mdspan.layout.right.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22339) *Effects*: Direct-non-list-initializes *extents_* with e[.](#mdspan.layout.right.cons-2.sentence-1) [🔗](#lib:layout_right::mapping,constructor_) `template constexpr explicit(!is_convertible_v) mapping(const mapping& other) noexcept; ` [3](#mdspan.layout.right.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22352) *Constraints*: is_constructible_v is true[.](#mdspan.layout.right.cons-3.sentence-1) [4](#mdspan.layout.right.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22356) *Preconditions*: other.required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.right.cons-4.sentence-1) [5](#mdspan.layout.right.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22361) *Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#mdspan.layout.right.cons-5.sentence-1) [🔗](#lib:layout_right::mapping,constructor__) `template constexpr explicit(!is_convertible_v) mapping(const layout_left::mapping& other) noexcept; ` [6](#mdspan.layout.right.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22374) *Constraints*: - [(6.1)](#mdspan.layout.right.cons-6.1) extents_type​::​rank() <= 1 is true, and - [(6.2)](#mdspan.layout.right.cons-6.2) is_constructible_v is true[.](#mdspan.layout.right.cons-6.sentence-1) [7](#mdspan.layout.right.cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22383) *Preconditions*: other.required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.right.cons-7.sentence-1) [8](#mdspan.layout.right.cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22388) *Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#mdspan.layout.right.cons-8.sentence-1) [🔗](#lib:layout_right::mapping,constructor___) `template constexpr explicit(!is_convertible_v) mapping(const LayoutRightPaddedMapping&) noexcept; ` [9](#mdspan.layout.right.cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22402) *Constraints*: - [(9.1)](#mdspan.layout.right.cons-9.1) *is-layout-right-padded-mapping-of* is true[.](#mdspan.layout.right.cons-9.1.sentence-1) - [(9.2)](#mdspan.layout.right.cons-9.2) is_constructible_v is true[.](#mdspan.layout.right.cons-9.2.sentence-1) [10](#mdspan.layout.right.cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22413) *Mandates*: If - [(10.1)](#mdspan.layout.right.cons-10.1) Extents​::​rank() is greater than one, - [(10.2)](#mdspan.layout.right.cons-10.2) Extents​::​static_extent(Extents​::​rank() - 1) does not equal dynamic_extent, and - [(10.3)](#mdspan.layout.right.cons-10.3) LayoutRightPaddedMapping​::​*static-padding-stride* does not equal dynamic_extent, then Extents​::​static_extent(Extents​::​rank() - 1) equalsLayoutRightPaddedMapping​::​*static-padding-stride*[.](#mdspan.layout.right.cons-10.sentence-1) [11](#mdspan.layout.right.cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22429) *Preconditions*: - [(11.1)](#mdspan.layout.right.cons-11.1) If extents_type​::​rank() > 1 is true, then other.stride(extents_type​::​rank() - 2) equalsother.extents().extent(extents_type​::​rank() - 1)[.](#mdspan.layout.right.cons-11.1.sentence-1) - [(11.2)](#mdspan.layout.right.cons-11.2) other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.right.cons-11.2.sentence-1) [12](#mdspan.layout.right.cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22441) *Effects*: Direct-non-list-initializes extents_ with other.extents()[.](#mdspan.layout.right.cons-12.sentence-1) [🔗](#lib:layout_right::mapping,constructor____) `template constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping& other) noexcept; ` [13](#mdspan.layout.right.cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22454) *Constraints*: is_constructible_v is true[.](#mdspan.layout.right.cons-13.sentence-1) [14](#mdspan.layout.right.cons-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22458) *Preconditions*: - [(14.1)](#mdspan.layout.right.cons-14.1) If extents_type​::​rank() > 0 is true, then for all r in the range [0, extents_type​::​rank()),other.stride(r) equalsother.extents().*rev-prod-of-extents*(r)[.](#mdspan.layout.right.cons-14.1.sentence-1) - [(14.2)](#mdspan.layout.right.cons-14.2) other.required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.right.cons-14.2.sentence-1) [15](#mdspan.layout.right.cons-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22471) *Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#mdspan.layout.right.cons-15.sentence-1) #### [23.7.3.4.6.3](#mdspan.layout.right.obs) Observers [[mdspan.layout.right.obs]](mdspan.layout.right.obs) [🔗](#lib:required_span_size,layout_right::mapping) `constexpr index_type required_span_size() const noexcept; ` [1](#mdspan.layout.right.obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22484) *Returns*: extents().*fwd-prod-of-extents*(extents_type​::​rank())[.](#mdspan.layout.right.obs-1.sentence-1) [🔗](#lib:operator(),layout_right::mapping) `template constexpr index_type operator()(Indices... i) const noexcept; ` [2](#mdspan.layout.right.obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22496) *Constraints*: - [(2.1)](#mdspan.layout.right.obs-2.1) sizeof...(Indices) == extents_type​::​rank() is true, - [(2.2)](#mdspan.layout.right.obs-2.2) (is_convertible_v && ...) is true, and - [(2.3)](#mdspan.layout.right.obs-2.3) (is_nothrow_constructible_v && ...) istrue[.](#mdspan.layout.right.obs-2.sentence-1) [3](#mdspan.layout.right.obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22508) *Preconditions*: extents_type​::​*index-cast*(i) is a multidimensional index in *extents_* ([[mdspan.overview]](#mdspan.overview "23.7.3.1 Overview"))[.](#mdspan.layout.right.obs-3.sentence-1) [4](#mdspan.layout.right.obs-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22513) *Effects*: Let P be a parameter pack such thatis_same_v, index_sequence> is true[.](#mdspan.layout.right.obs-4.sentence-1) Equivalent to:return ((static_cast(i) * stride(P)) + ... + 0); [🔗](#lib:stride,layout_right::mapping) `constexpr index_type stride(rank_type i) const noexcept; ` [5](#mdspan.layout.right.obs-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22531) *Constraints*: extents_type​::​rank() > 0 is true[.](#mdspan.layout.right.obs-5.sentence-1) [6](#mdspan.layout.right.obs-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22535) *Preconditions*: i < extents_type​::​rank() is true[.](#mdspan.layout.right.obs-6.sentence-1) [7](#mdspan.layout.right.obs-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22539) *Returns*: extents().*rev-prod-of-extents*(i)[.](#mdspan.layout.right.obs-7.sentence-1) [🔗](#lib:operator==,layout_right::mapping) `template friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; ` [8](#mdspan.layout.right.obs-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22551) *Constraints*: extents_type​::​rank() == OtherExtents​::​rank() is true[.](#mdspan.layout.right.obs-8.sentence-1) [9](#mdspan.layout.right.obs-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22555) *Effects*: Equivalent to: return x.extents() == y.extents(); #### [23.7.3.4.7](#mdspan.layout.stride) Class template layout_stride​::​mapping [[mdspan.layout.stride]](mdspan.layout.stride) #### [23.7.3.4.7.1](#mdspan.layout.stride.overview) Overview [[mdspan.layout.stride.overview]](mdspan.layout.stride.overview) [1](#mdspan.layout.stride.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22564) layout_stride provides a layout mapping where the strides are user-defined[.](#mdspan.layout.stride.overview-1.sentence-1) namespace std {templateclass layout_stride::mapping {public:using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_stride; private:static constexpr rank_type *rank_* = extents_type::rank(); // *exposition only*public:// [[mdspan.layout.stride.cons]](#mdspan.layout.stride.cons "23.7.3.4.7.3 Constructors"), constructorsconstexpr mapping() noexcept; constexpr mapping(const mapping&) noexcept = default; templateconstexpr mapping(const extents_type&, span) noexcept; templateconstexpr mapping(const extents_type&, const array&) noexcept; templateconstexpr explicit(*see below*) mapping(const StridedLayoutMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [[mdspan.layout.stride.obs]](#mdspan.layout.stride.obs "23.7.3.4.7.4 Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr array strides() const noexcept { return *strides_*; }constexpr index_type required_span_size() const noexcept; templateconstexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; }static constexpr bool is_always_exhaustive() noexcept { return false; }static constexpr bool is_always_strided() noexcept { return true; }static constexpr bool is_unique() noexcept { return true; }constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; }constexpr index_type stride(rank_type i) const noexcept { return *strides_*[i]; }templatefriend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept; private: extents_type *extents_*{}; // *exposition only* array *strides_*{}; // *exposition only*// [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6 Specializations of submdspan_­mapping"), submdspan mapping specializationtemplateconstexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; templatefriend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {return src.*submdspan-mapping-impl*(slices...); }};} [2](#mdspan.layout.stride.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22636) If Extents is not a specialization of extents, then the program is ill-formed[.](#mdspan.layout.stride.overview-2.sentence-1) [3](#mdspan.layout.stride.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22640) layout_stride​::​mapping is a trivially copyable type that models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") for each E[.](#mdspan.layout.stride.overview-3.sentence-1) [4](#mdspan.layout.stride.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22644) *Mandates*: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type typename Extents​::​index_type[.](#mdspan.layout.stride.overview-4.sentence-1) #### [23.7.3.4.7.2](#mdspan.layout.stride.expo) Exposition-only helpers [[mdspan.layout.stride.expo]](mdspan.layout.stride.expo) [1](#mdspan.layout.stride.expo-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22652) Let *REQUIRED-SPAN-SIZE*(e, strides) be: - [(1.1)](#mdspan.layout.stride.expo-1.1) 1, if e.rank() == 0 is true, - [(1.2)](#mdspan.layout.stride.expo-1.2) otherwise 0, if the size of the multidimensional index space e is 0, - [(1.3)](#mdspan.layout.stride.expo-1.3) otherwise 1 plus the sum of products of(e.extent(r) - 1) andextents_type::*index-cast*(strides[r]) for all r in the range [0, e.rank())[.](#mdspan.layout.stride.expo-1.sentence-1) [2](#mdspan.layout.stride.expo-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22668) Let *OFFSET*(m) be: - [(2.1)](#mdspan.layout.stride.expo-2.1) m(), if e.rank() == 0 is true, - [(2.2)](#mdspan.layout.stride.expo-2.2) otherwise 0, if the size of the multidimensional index space e is 0, - [(2.3)](#mdspan.layout.stride.expo-2.3) otherwise m(z...) for a pack of integers z that is a multidimensional index in m.extents() and each element of z equals 0[.](#mdspan.layout.stride.expo-2.sentence-1) [3](#mdspan.layout.stride.expo-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22681) Let *is-extents* be the exposition-only variable template defined as follows:templateconstexpr bool *is-extents* = false; // *exposition only*templateconstexpr bool *is-extents*> = true; // *exposition only* [4](#mdspan.layout.stride.expo-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22691) Let [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]") be the exposition-only concept defined as follows:templateconcept [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]") = requires { // *exposition only*requires *is-extents*; { M::is_always_strided() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { M::is_always_exhaustive() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { M::is_always_unique() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); bool_constant::value; bool_constant::value; bool_constant::value;}; [*Note [1](#mdspan.layout.stride.expo-note-1)*: This concept checks that the functionsM​::​is_always_strided(),M​::​is_always_exhaustive(), andM​::​is_always_unique() exist, are constant expressions, and have a return type of bool[.](#mdspan.layout.stride.expo-4.sentence-1) — *end note*] #### [23.7.3.4.7.3](#mdspan.layout.stride.cons) Constructors [[mdspan.layout.stride.cons]](mdspan.layout.stride.cons) [🔗](#lib:layout_stride::mapping,constructor) `constexpr mapping() noexcept; ` [1](#mdspan.layout.stride.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22723) *Preconditions*: layout_right​::​mapping().required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.stride.cons-1.sentence-1) [2](#mdspan.layout.stride.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22728) *Effects*: Direct-non-list-initializes *extents_* with extents_type(), and for all d in the range [0, *rank_*), direct-non-list-initializes *strides_*[d] withlayout_right​::​mapping().stride(d)[.](#mdspan.layout.stride.cons-2.sentence-1) [🔗](#lib:layout_stride::mapping,constructor_) `template constexpr mapping(const extents_type& e, span s) noexcept; template constexpr mapping(const extents_type& e, const array& s) noexcept; ` [3](#mdspan.layout.stride.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22745) *Constraints*: - [(3.1)](#mdspan.layout.stride.cons-3.1) is_convertible_v is true, and - [(3.2)](#mdspan.layout.stride.cons-3.2) is_nothrow_constructible_v is true[.](#mdspan.layout.stride.cons-3.sentence-1) [4](#mdspan.layout.stride.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22754) *Preconditions*: - [(4.1)](#mdspan.layout.stride.cons-4.1) The result of converting s[i] to index_type is greater than 0 for all i in the range [0, *rank_*)[.](#mdspan.layout.stride.cons-4.1.sentence-1) - [(4.2)](#mdspan.layout.stride.cons-4.2) *REQUIRED-SPAN-SIZE*(e, s) is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.layout.stride.cons-4.2.sentence-1) - [(4.3)](#mdspan.layout.stride.cons-4.3) If *rank_* is greater than 0, then there exists a permutation P of the integers in the range [0, *rank_*), such that s[pi] >= s[pi−1] * e.extent(pi−1) is true for all i in the range [1, *rank_*), where pi is the ith element of P[.](#mdspan.layout.stride.cons-4.3.sentence-1) [*Note [1](#mdspan.layout.stride.cons-note-1)*: For layout_stride, this condition is necessary and sufficient for is_unique() to be true[.](#mdspan.layout.stride.cons-4.3.sentence-2) — *end note*] [5](#mdspan.layout.stride.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22778) *Effects*: Direct-non-list-initializes *extents_* with e, and for all d in the range [0, *rank_*), direct-non-list-initializes strides_[d] with as_const(s[d])[.](#mdspan.layout.stride.cons-5.sentence-1) [🔗](#lib:layout_stride::mapping,constructor__) `template constexpr explicit(see below) mapping(const StridedLayoutMapping& other) noexcept; ` [6](#mdspan.layout.stride.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22793) *Constraints*: - [(6.1)](#mdspan.layout.stride.cons-6.1) [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]") is satisfied[.](#mdspan.layout.stride.cons-6.1.sentence-1) - [(6.2)](#mdspan.layout.stride.cons-6.2) is_constructible_v is true[.](#mdspan.layout.stride.cons-6.2.sentence-2) - [(6.3)](#mdspan.layout.stride.cons-6.3) StridedLayoutMapping​::​is_always_unique() is true[.](#mdspan.layout.stride.cons-6.3.sentence-1) - [(6.4)](#mdspan.layout.stride.cons-6.4) StridedLayoutMapping​::​is_always_strided() is true[.](#mdspan.layout.stride.cons-6.4.sentence-1) [7](#mdspan.layout.stride.cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22806) *Preconditions*: - [(7.1)](#mdspan.layout.stride.cons-7.1) StridedLayoutMapping meets the layout mapping requirements ([[mdspan.layout.reqmts]](#mdspan.layout.reqmts "23.7.3.4.2 Requirements")), - [(7.2)](#mdspan.layout.stride.cons-7.2) other.stride(r) > 0 is true for every rank index r of extents(), - [(7.3)](#mdspan.layout.stride.cons-7.3) other.required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")), and - [(7.4)](#mdspan.layout.stride.cons-7.4) *OFFSET*(other) == 0 is true[.](#mdspan.layout.stride.cons-7.sentence-1) [8](#mdspan.layout.stride.cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22821) *Effects*: Direct-non-list-initializes *extents_* with other.extents(), and for all d in the range [0, *rank_*), direct-non-list-initializes *strides_*[d] with other.stride(d)[.](#mdspan.layout.stride.cons-8.sentence-1) [9](#mdspan.layout.stride.cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22828) Remarks: The expression inside explicit is equivalent to:!(is_convertible_v &&(*is-mapping-of* ||*is-mapping-of* ||*is-layout-left-padded-mapping-of* ||*is-layout-right-padded-mapping-of* ||*is-mapping-of*)) #### [23.7.3.4.7.4](#mdspan.layout.stride.obs) Observers [[mdspan.layout.stride.obs]](mdspan.layout.stride.obs) [🔗](#lib:required_span_size,layout_stride::mapping) `constexpr index_type required_span_size() const noexcept; ` [1](#mdspan.layout.stride.obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22848) *Returns*: *REQUIRED-SPAN-SIZE*(extents(), *strides_*)[.](#mdspan.layout.stride.obs-1.sentence-1) [🔗](#lib:operator(),layout_stride::mapping) `template constexpr index_type operator()(Indices... i) const noexcept; ` [2](#mdspan.layout.stride.obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22860) *Constraints*: - [(2.1)](#mdspan.layout.stride.obs-2.1) sizeof...(Indices) == *rank_* is true, - [(2.2)](#mdspan.layout.stride.obs-2.2) (is_convertible_v && ...) is true, and - [(2.3)](#mdspan.layout.stride.obs-2.3) (is_nothrow_constructible_v && ...) is true[.](#mdspan.layout.stride.obs-2.sentence-1) [3](#mdspan.layout.stride.obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22871) *Preconditions*: extents_type​::​*index-cast*(i) is a multidimensional index in *extents_* ([[mdspan.overview]](#mdspan.overview "23.7.3.1 Overview"))[.](#mdspan.layout.stride.obs-3.sentence-1) [4](#mdspan.layout.stride.obs-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22876) *Effects*: Let P be a parameter pack such thatis_same_v, index_sequence> is true[.](#mdspan.layout.stride.obs-4.sentence-1) Equivalent to:return ((static_cast(i) * stride(P)) + ... + 0); [🔗](#lib:is_exhaustive,layout_stride::mapping) `constexpr bool is_exhaustive() const noexcept; ` [5](#mdspan.layout.stride.obs-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22895) *Returns*: - [(5.1)](#mdspan.layout.stride.obs-5.1) true if *rank_* is 0[.](#mdspan.layout.stride.obs-5.1.sentence-1) - [(5.2)](#mdspan.layout.stride.obs-5.2) Otherwise, true if there is a permutation P of the integers in the range [0, *rank_*) such that stride(p0) equals 1, andstride(pi) equals stride(pi−1) * extents().extent(pi−1) for i in the range [1, *rank_*), where pi is the ith element of P[.](#mdspan.layout.stride.obs-5.2.sentence-1) - [(5.3)](#mdspan.layout.stride.obs-5.3) Otherwise, false[.](#mdspan.layout.stride.obs-5.3.sentence-1) [🔗](#lib:operator==,layout_stride::mapping) `template friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept; ` [6](#mdspan.layout.stride.obs-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22919) *Constraints*: - [(6.1)](#mdspan.layout.stride.obs-6.1) [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]") is satisfied[.](#mdspan.layout.stride.obs-6.1.sentence-1) - [(6.2)](#mdspan.layout.stride.obs-6.2) *rank_* == OtherMapping​::​extents_type​::​rank() is true[.](#mdspan.layout.stride.obs-6.2.sentence-1) - [(6.3)](#mdspan.layout.stride.obs-6.3) OtherMapping​::​is_always_strided() is true[.](#mdspan.layout.stride.obs-6.3.sentence-1) [7](#mdspan.layout.stride.obs-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22930) *Preconditions*: OtherMapping meets the layout mapping requirements ([[mdspan.layout.policy.reqmts]](#mdspan.layout.policy.reqmts "23.7.3.4.3 Layout mapping policy requirements"))[.](#mdspan.layout.stride.obs-7.sentence-1) [8](#mdspan.layout.stride.obs-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22934) *Returns*: true if x.extents() == y.extents() is true,*OFFSET*(y) == 0 is true, and each of x.stride(r) == y.stride(r) is true for r in the range [0, x.extents().rank())[.](#mdspan.layout.stride.obs-8.sentence-1) Otherwise, false[.](#mdspan.layout.stride.obs-8.sentence-2) #### [23.7.3.4.8](#mdspan.layout.leftpad) Class template layout_left_padded​::​mapping [[mdspan.layout.leftpad]](mdspan.layout.leftpad) #### [23.7.3.4.8.1](#mdspan.layout.leftpad.overview) Overview [[mdspan.layout.leftpad.overview]](mdspan.layout.leftpad.overview) [1](#mdspan.layout.leftpad.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22947) layout_left_padded provides a layout mapping that behaves like layout_left​::​mapping, except that the padding stride stride(1) can be greater than or equal to extent(0)[.](#mdspan.layout.leftpad.overview-1.sentence-1) namespace std {templatetemplateclass layout_left_padded::mapping {public:static constexpr size_t padding_value = PaddingValue; using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_left_padded; private:static constexpr size_t *rank_* = extents_type::rank(); // *exposition only*static constexpr size_t *first-static-extent* = // *exposition only* extents_type::static_extent(0); // [[mdspan.layout.leftpad.expo]](#mdspan.layout.leftpad.expo "23.7.3.4.8.2 Exposition-only members"), exposition-only membersstatic constexpr size_t *static-padding-stride* = *see below*; // *exposition only*public:// [[mdspan.layout.leftpad.cons]](#mdspan.layout.leftpad.cons "23.7.3.4.8.3 Constructors"), constructorsconstexpr mapping() noexcept : mapping(extents_type{}) {}constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&); templateconstexpr mapping(const extents_type&, OtherIndexType); templateconstexpr explicit(!is_convertible_v) mapping(const layout_left::mapping&); templateconstexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping&); templateconstexpr explicit(*see below*) mapping(const LayoutLeftPaddedMapping&); templateconstexpr explicit(*see below*) mapping(const LayoutRightPaddedMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [[mdspan.layout.leftpad.obs]](#mdspan.layout.leftpad.obs "23.7.3.4.8.4 Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr array strides() const noexcept; constexpr index_type required_span_size() const noexcept; templateconstexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; }static constexpr bool is_always_exhaustive() noexcept; static constexpr bool is_always_strided() noexcept { return true; }static constexpr bool is_unique() noexcept { return true; }constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; }constexpr index_type stride(rank_type) const noexcept; templatefriend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept; private:// [[mdspan.layout.leftpad.expo]](#mdspan.layout.leftpad.expo "23.7.3.4.8.2 Exposition-only members"), exposition-only members index_type *stride-1* = *static-padding-stride*; // *exposition only* extents_type *extents_*{}; // *exposition only*// [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6 Specializations of submdspan_­mapping"), submdspan mapping specializationtemplateconstexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; templatefriend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {return src.*submdspan-mapping-impl*(slices...); }};} [2](#mdspan.layout.leftpad.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23035) If Extents is not a specialization of extents, then the program is ill-formed[.](#mdspan.layout.leftpad.overview-2.sentence-1) [3](#mdspan.layout.leftpad.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23039) layout_left_padded​::​mapping is a trivially copyable type that models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") for each E[.](#mdspan.layout.leftpad.overview-3.sentence-1) [4](#mdspan.layout.leftpad.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23043) Throughout [[mdspan.layout.leftpad]](#mdspan.layout.leftpad "23.7.3.4.8 Class template layout_­left_­padded​::​mapping"), let P_rank be the following size *rank_* parameter pack of size_t values: - [(4.1)](#mdspan.layout.leftpad.overview-4.1) the empty parameter pack, if *rank_* equals zero; - [(4.2)](#mdspan.layout.leftpad.overview-4.2) otherwise, 0zu, if *rank_* equals one; - [(4.3)](#mdspan.layout.leftpad.overview-4.3) otherwise, the parameter pack 0zu, 1zu, …, *rank_*- 1[.](#mdspan.layout.leftpad.overview-4.sentence-1) [5](#mdspan.layout.leftpad.overview-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23056) *Mandates*: - [(5.1)](#mdspan.layout.leftpad.overview-5.1) If rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type index_type[.](#mdspan.layout.leftpad.overview-5.1.sentence-1) - [(5.2)](#mdspan.layout.leftpad.overview-5.2) padding_value is representable as a value of type index_type[.](#mdspan.layout.leftpad.overview-5.2.sentence-1) - [(5.3)](#mdspan.layout.leftpad.overview-5.3) If * [(5.3.1)](#mdspan.layout.leftpad.overview-5.3.1) *rank_* is greater than one, * [(5.3.2)](#mdspan.layout.leftpad.overview-5.3.2) padding_value does not equal dynamic_extent, and * [(5.3.3)](#mdspan.layout.leftpad.overview-5.3.3) *first-static-extent* does not equal dynamic_extent, then *LEAST-MULTIPLE-AT-LEAST*(padding_value, *first-static-extent*) is representable as a value of type size_t, and is representable as a value of type index_type[.](#mdspan.layout.leftpad.overview-5.3.sentence-1) - [(5.4)](#mdspan.layout.leftpad.overview-5.4) If * [(5.4.1)](#mdspan.layout.leftpad.overview-5.4.1) *rank_* is greater than one, * [(5.4.2)](#mdspan.layout.leftpad.overview-5.4.2) padding_value does not equal dynamic_extent, and * [(5.4.3)](#mdspan.layout.leftpad.overview-5.4.3) extents_type​::​static_extent(k) does not equal dynamic_extent for all k in the range [0, extents_type​::​rank()), then the product of*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.static_extent(0)) and all values ext.static_extent(k) with k in the range of [1, *rank_*) is representable as a value of type size_t, and is representable as a value of type index_type[.](#mdspan.layout.leftpad.overview-5.4.sentence-1) #### [23.7.3.4.8.2](#mdspan.layout.leftpad.expo) Exposition-only members [[mdspan.layout.leftpad.expo]](mdspan.layout.leftpad.expo) [🔗](#mdspan.layout.leftpad.expo-itemdecl:1) `static constexpr size_t static-padding-stride = see below; ` [1](#mdspan.layout.leftpad.expo-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23104) The value is - [(1.1)](#mdspan.layout.leftpad.expo-1.1) 0, if *rank_* equals zero or one; - [(1.2)](#mdspan.layout.leftpad.expo-1.2) otherwise, dynamic_extent, if padding_value or *first-static-extent* equalsdynamic_extent; - [(1.3)](#mdspan.layout.leftpad.expo-1.3) otherwise, the size_t value which is*LEAST-MULTIPLE-AT-LEAST*(padding_value, *first-static-extent*)[.](#mdspan.layout.leftpad.expo-1.sentence-1) [🔗](#mdspan.layout.leftpad.expo-itemdecl:2) `index_type stride-1 = static-padding-stride; ` [2](#mdspan.layout.leftpad.expo-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23124) *Recommended practice*: Implementations should not store this value if *static-padding-stride* is not dynamic_extent[.](#mdspan.layout.leftpad.expo-2.sentence-1) [*Note [1](#mdspan.layout.leftpad.expo-note-1)*: Using extents instead ofindex_type as the type of *stride-1* would achieve this[.](#mdspan.layout.leftpad.expo-2.sentence-2) — *end note*] #### [23.7.3.4.8.3](#mdspan.layout.leftpad.cons) Constructors [[mdspan.layout.leftpad.cons]](mdspan.layout.leftpad.cons) [🔗](#lib:layout_left_padded::mapping,constructor) `constexpr mapping(const extents_type& ext); ` [1](#mdspan.layout.leftpad.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23142) *Preconditions*: - [(1.1)](#mdspan.layout.leftpad.cons-1.1) The size of the multidimensional index space ext is representable as a value of type index_type[.](#mdspan.layout.leftpad.cons-1.1.sentence-1) - [(1.2)](#mdspan.layout.leftpad.cons-1.2) If *rank_* is greater than one andpadding_value does not equal dynamic_extent, then *LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(0)) is representable as a value of type *index_type*[.](#mdspan.layout.leftpad.cons-1.2.sentence-1) - [(1.3)](#mdspan.layout.leftpad.cons-1.3) If *rank_* is greater than one andpadding_value does not equal dynamic_extent, then the product of*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(0)) and all values ext.extent(k) with k in the range of [1, *rank_*) is representable as a value of type index_type[.](#mdspan.layout.leftpad.cons-1.3.sentence-1) [2](#mdspan.layout.leftpad.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23163) *Effects*: - [(2.1)](#mdspan.layout.leftpad.cons-2.1) Direct-non-list-initializes *extents_* with ext; and - [(2.2)](#mdspan.layout.leftpad.cons-2.2) if *rank_* is greater than one, direct-non-list-initializes *stride-1* * [(2.2.1)](#mdspan.layout.leftpad.cons-2.2.1) with ext.extent(0) if padding_value is dynamic_extent, * [(2.2.2)](#mdspan.layout.leftpad.cons-2.2.2) otherwise with*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(0))[.](#mdspan.layout.leftpad.cons-2.sentence-1) [🔗](#lib:layout_left_padded::mapping,constructor_) `template constexpr mapping(const extents_type& ext, OtherIndexType pad); ` [3](#mdspan.layout.leftpad.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23188) *Constraints*: - [(3.1)](#mdspan.layout.leftpad.cons-3.1) is_convertible_v is true[.](#mdspan.layout.leftpad.cons-3.1.sentence-1) - [(3.2)](#mdspan.layout.leftpad.cons-3.2) is_nothrow_constructible_v is true[.](#mdspan.layout.leftpad.cons-3.2.sentence-1) [4](#mdspan.layout.leftpad.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23197) *Preconditions*: - [(4.1)](#mdspan.layout.leftpad.cons-4.1) pad is representable as a value of type index_type[.](#mdspan.layout.leftpad.cons-4.1.sentence-1) - [(4.2)](#mdspan.layout.leftpad.cons-4.2) extents_type​::​index-cast(pad) is greater than zero[.](#mdspan.layout.leftpad.cons-4.2.sentence-1) - [(4.3)](#mdspan.layout.leftpad.cons-4.3) If *rank_* is greater than one, then *LEAST-MULTIPLE-AT-LEAST*(pad, ext.extent(0)) is representable as a value of type index_type. - [(4.4)](#mdspan.layout.leftpad.cons-4.4) If *rank_* is greater than one, then the product of*LEAST-MULTIPLE-AT-LEAST*(pad, ext.extent(0)) and all values ext.extent(k) with k in the range of [1, *rank_*) is representable as a value of type index_type[.](#mdspan.layout.leftpad.cons-4.4.sentence-1) - [(4.5)](#mdspan.layout.leftpad.cons-4.5) If padding_value is not equal to dynamic_extent,padding_value equals extents_type​::​*index-cast*(pad)[.](#mdspan.layout.leftpad.cons-4.5.sentence-1) [5](#mdspan.layout.leftpad.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23220) *Effects*: Direct-non-list-initializes *extents_* with ext, and if *rank_* is greater than one, direct-non-list-initializes *stride-1* with*LEAST-MULTIPLE-AT-LEAST*(pad, ext.extent(0))[.](#mdspan.layout.leftpad.cons-5.sentence-1) [🔗](#lib:layout_left_padded::mapping,constructor__) `template constexpr explicit(!is_convertible_v) mapping(const layout_left::mapping& other); ` [6](#mdspan.layout.leftpad.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23236) *Constraints*: is_constructible_v is true[.](#mdspan.layout.leftpad.cons-6.sentence-1) [7](#mdspan.layout.leftpad.cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23240) *Mandates*: If OtherExtents​::​rank() is greater than 1, then(*static-padding-stride* == dynamic_extent) ||(OtherExtents::static_extent(0) == dynamic_extent) ||(*static-padding-stride* == OtherExtents::static_extent(0)) is true[.](#mdspan.layout.leftpad.cons-7.sentence-1) [8](#mdspan.layout.leftpad.cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23250) *Preconditions*: - [(8.1)](#mdspan.layout.leftpad.cons-8.1) If extents_type​::​rank() > 1 is true andpadding_value == dynamic_extent is false, then other.stride(1) equals*LEAST-MULTIPLE-AT-LEAST*(padding_value, extents_type::*index-cast*(other.extents().extent(0))) and - [(8.2)](#mdspan.layout.leftpad.cons-8.2) other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.leftpad.cons-8.sentence-1) [9](#mdspan.layout.leftpad.cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23267) *Effects*: Equivalent to mapping(other.extents())[.](#mdspan.layout.leftpad.cons-9.sentence-1) [🔗](#lib:layout_left_padded::mapping,constructor___) `template constexpr explicit(rank_ > 0) mapping(const layout_stride::mapping& other); ` [10](#mdspan.layout.leftpad.cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23280) *Constraints*: is_constructible_v is true[.](#mdspan.layout.leftpad.cons-10.sentence-1) [11](#mdspan.layout.leftpad.cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23284) *Preconditions*: - [(11.1)](#mdspan.layout.leftpad.cons-11.1) If *rank_* is greater than 1 andpadding_value does not equal dynamic_extent, then other.stride(1) equals*LEAST-MULTIPLE-AT-LEAST*(padding_value, extents_type::*index-cast*(other.extents().extent(0))) - [(11.2)](#mdspan.layout.leftpad.cons-11.2) If *rank_* is greater than 0, then other.stride(0) equals 1[.](#mdspan.layout.leftpad.cons-11.2.sentence-1) - [(11.3)](#mdspan.layout.leftpad.cons-11.3) If *rank_* is greater than 2, then for all r in the range [2, *rank_*),other.stride(r) equals(other.extents().*fwd-prod-of-extents*(r) / other.extents().extent(0)) * other.stride(1) - [(11.4)](#mdspan.layout.leftpad.cons-11.4) other.required_span_size() is representable as a value of type *index_type*[.](#mdspan.layout.leftpad.cons-11.4.sentence-1) [12](#mdspan.layout.leftpad.cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23310) *Effects*: - [(12.1)](#mdspan.layout.leftpad.cons-12.1) Direct-non-list-initializes *extents_* with other.extents() and - [(12.2)](#mdspan.layout.leftpad.cons-12.2) if *rank_* is greater than one, direct-non-list-initializes *stride-1* withother.stride(1)[.](#mdspan.layout.leftpad.cons-12.sentence-1) [🔗](#lib:layout_left_padded::mapping,constructor____) `template constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping& other); ` [13](#mdspan.layout.leftpad.cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23330) *Constraints*: - [(13.1)](#mdspan.layout.leftpad.cons-13.1) *is-layout-left-padded-mapping-of* is true[.](#mdspan.layout.leftpad.cons-13.1.sentence-1) - [(13.2)](#mdspan.layout.leftpad.cons-13.2) is_constructible_v is true[.](#mdspan.layout.leftpad.cons-13.2.sentence-1) [14](#mdspan.layout.leftpad.cons-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23341) *Mandates*: If *rank_* is greater than 1, thenpadding_value == dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent || padding_value == LayoutLeftPaddedMapping::padding_value is true[.](#mdspan.layout.leftpad.cons-14.sentence-1) [15](#mdspan.layout.leftpad.cons-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23352) *Preconditions*: - [(15.1)](#mdspan.layout.leftpad.cons-15.1) If *rank_* is greater than 1 andpadding_value does not equal dynamic_extent, then other.stride(1) equals*LEAST-MULTIPLE-AT-LEAST*(padding_value, extents_type::*index-cast*(other.extent(0))) - [(15.2)](#mdspan.layout.leftpad.cons-15.2) other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.leftpad.cons-15.sentence-1) [16](#mdspan.layout.leftpad.cons-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23368) *Effects*: - [(16.1)](#mdspan.layout.leftpad.cons-16.1) Direct-non-list-initializes *extents_* with other.extents() and - [(16.2)](#mdspan.layout.leftpad.cons-16.2) if *rank_* is greater than one, direct-non-list-initializes *stride-1* with other.stride(1)[.](#mdspan.layout.leftpad.cons-16.sentence-1) [17](#mdspan.layout.leftpad.cons-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23378) *Remarks*: The expression inside explicit is equivalent to:rank_> 1 &&(padding_value != dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent) [🔗](#lib:layout_left_padded::mapping,constructor_____) `template constexpr explicit(see below) mapping(const LayoutRightPaddedMapping& other) noexcept; ` [18](#mdspan.layout.leftpad.cons-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23396) *Constraints*: - [(18.1)](#mdspan.layout.leftpad.cons-18.1) *is-layout-right-padded-mapping-of* is true or *is-mapping-of* is true[.](#mdspan.layout.leftpad.cons-18.1.sentence-1) - [(18.2)](#mdspan.layout.leftpad.cons-18.2) *rank_* equals zero or one[.](#mdspan.layout.leftpad.cons-18.2.sentence-1) - [(18.3)](#mdspan.layout.leftpad.cons-18.3) is_constructible_v is true[.](#mdspan.layout.leftpad.cons-18.3.sentence-1) [19](#mdspan.layout.leftpad.cons-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23411) *Preconditions*: other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.leftpad.cons-19.sentence-1) [20](#mdspan.layout.leftpad.cons-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23416) *Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#mdspan.layout.leftpad.cons-20.sentence-1) [21](#mdspan.layout.leftpad.cons-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23420) *Remarks*: The expression inside explicit is equivalent to:!is_convertible_v [*Note [1](#mdspan.layout.leftpad.cons-note-1)*: Neither the input mapping nor the mapping to be constructed uses the padding stride in the rank-0 or rank-1 case, so the padding stride does not affect either the constraints or the preconditions[.](#mdspan.layout.leftpad.cons-21.sentence-2) — *end note*] #### [23.7.3.4.8.4](#mdspan.layout.leftpad.obs) Observers [[mdspan.layout.leftpad.obs]](mdspan.layout.leftpad.obs) [🔗](#mdspan.layout.leftpad.obs-itemdecl:1) `constexpr array strides() const noexcept; ` [1](#mdspan.layout.leftpad.obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23442) *Returns*: array({stride(P_rank)...})[.](#mdspan.layout.leftpad.obs-1.sentence-1) [🔗](#mdspan.layout.leftpad.obs-itemdecl:2) `constexpr index_type required_span_size() const noexcept; ` [2](#mdspan.layout.leftpad.obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23452) *Returns*: - [(2.1)](#mdspan.layout.leftpad.obs-2.1) 0 if the multidimensional index space *extents_* is empty, - [(2.2)](#mdspan.layout.leftpad.obs-2.2) otherwise, *this(((*extents_*(P_rank) - index_type(1))...)) + 1[.](#mdspan.layout.leftpad.obs-2.sentence-1) [🔗](#mdspan.layout.leftpad.obs-itemdecl:3) `template constexpr size_t operator()(Indices... idxs) const noexcept; ` [3](#mdspan.layout.leftpad.obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23468) *Constraints*: - [(3.1)](#mdspan.layout.leftpad.obs-3.1) sizeof...(Indices) == *rank_* is true[.](#mdspan.layout.leftpad.obs-3.1.sentence-1) - [(3.2)](#mdspan.layout.leftpad.obs-3.2) (is_convertible_v && ...) is true[.](#mdspan.layout.leftpad.obs-3.2.sentence-1) - [(3.3)](#mdspan.layout.leftpad.obs-3.3) (is_nothrow_constructible_v && ...) is true[.](#mdspan.layout.leftpad.obs-3.3.sentence-1) [4](#mdspan.layout.leftpad.obs-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23479) *Preconditions*: extents_type​::​*index-cast*(idxs) is a multidimensional index in extents() ([[mdspan.overview]](#mdspan.overview "23.7.3.1 Overview"))[.](#mdspan.layout.leftpad.obs-4.sentence-1) [5](#mdspan.layout.leftpad.obs-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23484) *Returns*: ((static_cast(idxs) * stride(P_rank)) + ... + 0)[.](#mdspan.layout.leftpad.obs-5.sentence-1) [🔗](#mdspan.layout.leftpad.obs-itemdecl:4) `static constexpr bool is_always_exhaustive() noexcept; ` [6](#mdspan.layout.leftpad.obs-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23494) *Returns*: - [(6.1)](#mdspan.layout.leftpad.obs-6.1) If *rank_* equals zero or one, then true; - [(6.2)](#mdspan.layout.leftpad.obs-6.2) otherwise, if neither *static-padding-stride* nor *first-static-extent* equal dynamic_extent, then *static-padding-stride* == *first-static-extent*; - [(6.3)](#mdspan.layout.leftpad.obs-6.3) otherwise, false[.](#mdspan.layout.leftpad.obs-6.sentence-1) [🔗](#mdspan.layout.leftpad.obs-itemdecl:5) `constexpr bool is_exhaustive() const noexcept; ` [7](#mdspan.layout.leftpad.obs-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23514) *Returns*: true if *rank_* equals zero or one; otherwise, extents_.extent(0) == stride(1)[.](#mdspan.layout.leftpad.obs-7.sentence-1) [🔗](#mdspan.layout.leftpad.obs-itemdecl:6) `constexpr index_type stride(rank_type r) const noexcept; ` [8](#mdspan.layout.leftpad.obs-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23525) *Preconditions*: r is smaller than *rank_*[.](#mdspan.layout.leftpad.obs-8.sentence-1) [9](#mdspan.layout.leftpad.obs-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23529) *Returns*: - [(9.1)](#mdspan.layout.leftpad.obs-9.1) If r equals zero: 1; - [(9.2)](#mdspan.layout.leftpad.obs-9.2) otherwise, if r equals one: *stride-1*; - [(9.3)](#mdspan.layout.leftpad.obs-9.3) otherwise, the product of *stride-1* and all values extents_.extent(k) with k in the range [1, r)[.](#mdspan.layout.leftpad.obs-9.sentence-1) [🔗](#mdspan.layout.leftpad.obs-itemdecl:7) `template friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept; ` [10](#mdspan.layout.leftpad.obs-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23548) *Constraints*: - [(10.1)](#mdspan.layout.leftpad.obs-10.1) *is-layout-left-padded-mapping-of* is true[.](#mdspan.layout.leftpad.obs-10.1.sentence-1) - [(10.2)](#mdspan.layout.leftpad.obs-10.2) LayoutLeftPaddedMapping​::​extents_type​::​rank() == rank_ is true[.](#mdspan.layout.leftpad.obs-10.2.sentence-1) [11](#mdspan.layout.leftpad.obs-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23558) *Returns*: true if x.extents() == y.extents() is true and*rank_* < 2 || x.stride(1) == y. stride(1) is true[.](#mdspan.layout.leftpad.obs-11.sentence-1) Otherwise, false[.](#mdspan.layout.leftpad.obs-11.sentence-2) #### [23.7.3.4.9](#mdspan.layout.rightpad) Class template layout_right_padded​::​mapping [[mdspan.layout.rightpad]](mdspan.layout.rightpad) #### [23.7.3.4.9.1](#mdspan.layout.rightpad.overview) Overview [[mdspan.layout.rightpad.overview]](mdspan.layout.rightpad.overview) [1](#mdspan.layout.rightpad.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23569) layout_right_padded provides a layout mapping that behaves like layout_right​::​mapping, except that the padding stride stride(extents_type​::​rank() - 2) can be greater than or equal toextents_type​::​extent(extents_type​::​rank() - 1)[.](#mdspan.layout.rightpad.overview-1.sentence-1) namespace std {templatetemplateclass layout_right_padded::mapping {public:static constexpr size_t padding_value = PaddingValue; using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_right_padded; private:static constexpr size_t *rank_* = extents_type::rank(); // *exposition only*static constexpr size_t *last-static-extent* = // *exposition only* extents_type::static_extent(*rank_* - 1); // [[mdspan.layout.rightpad.expo]](#mdspan.layout.rightpad.expo "23.7.3.4.9.2 Exposition-only members"), exposition-only membersstatic constexpr size_t *static-padding-stride* = *see below*; // *exposition only*public:// [[mdspan.layout.rightpad.cons]](#mdspan.layout.rightpad.cons "23.7.3.4.9.3 Constructors"), constructorsconstexpr mapping() noexcept : mapping(extents_type{}) {}constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&); templateconstexpr mapping(const extents_type&, OtherIndexType); templateconstexpr explicit(!is_convertible_v) mapping(const layout_right::mapping&); templateconstexpr explicit(rank_ > 0) mapping(const layout_stride::mapping&); templateconstexpr explicit(*see below*) mapping(const LayoutRightPaddedMapping&); templateconstexpr explicit(*see below*) mapping(const LayoutLeftPaddedMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [[mdspan.layout.rightpad.obs]](#mdspan.layout.rightpad.obs "23.7.3.4.9.4 Observers"), observersconstexpr const extents_type& extents() const noexcept { return extents_; }constexpr array strides() const noexcept; constexpr index_type required_span_size() const noexcept; templateconstexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; }static constexpr bool is_always_exhaustive() noexcept; static constexpr bool is_always_strided() noexcept { return true; }static constexpr bool is_unique() noexcept { return true; }constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; }constexpr index_type stride(rank_type) const noexcept; templatefriend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept; private:// [[mdspan.layout.rightpad.expo]](#mdspan.layout.rightpad.expo "23.7.3.4.9.2 Exposition-only members"), exposition-only members index_type *stride-rm2* = *static-padding-stride*; // *exposition only* extents_type *extents_*{}; // *exposition only*// [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6 Specializations of submdspan_­mapping"), submdspan mapping specializationtemplateconstexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; templatefriend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {return src.*submdspan-mapping-impl*(slices...); }};} [2](#mdspan.layout.rightpad.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23661) If Extents is not a specialization of extents, then the program is ill-formed[.](#mdspan.layout.rightpad.overview-2.sentence-1) [3](#mdspan.layout.rightpad.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23665) layout_right_padded​::​mapping is a trivially copyable type that models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") for each E[.](#mdspan.layout.rightpad.overview-3.sentence-1) [4](#mdspan.layout.rightpad.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23669) Throughout [[mdspan.layout.rightpad]](#mdspan.layout.rightpad "23.7.3.4.9 Class template layout_­right_­padded​::​mapping"), let P_rank be the following size *rank_* parameter pack of size_t values: - [(4.1)](#mdspan.layout.rightpad.overview-4.1) the empty parameter pack, if *rank_* equals zero; - [(4.2)](#mdspan.layout.rightpad.overview-4.2) otherwise, 0zu, if *rank_* equals one; - [(4.3)](#mdspan.layout.rightpad.overview-4.3) otherwise, the parameter pack 0zu, 1zu, …, *rank_*- 1[.](#mdspan.layout.rightpad.overview-4.sentence-1) [5](#mdspan.layout.rightpad.overview-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23682) *Mandates*: - [(5.1)](#mdspan.layout.rightpad.overview-5.1) If rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type index_type[.](#mdspan.layout.rightpad.overview-5.1.sentence-1) - [(5.2)](#mdspan.layout.rightpad.overview-5.2) padding_value is representable as a value of type index_type[.](#mdspan.layout.rightpad.overview-5.2.sentence-1) - [(5.3)](#mdspan.layout.rightpad.overview-5.3) If * [(5.3.1)](#mdspan.layout.rightpad.overview-5.3.1) *rank_* is greater than one, * [(5.3.2)](#mdspan.layout.rightpad.overview-5.3.2) padding_value does not equal dynamic_extent, and * [(5.3.3)](#mdspan.layout.rightpad.overview-5.3.3) *last-static-extent* does not equal dynamic_extent, then *LEAST-MULTIPLE-AT-LEAST*(padding_value, *last-static-extent*) is representable as a value of type size_t, and is representable as a value of type index_type[.](#mdspan.layout.rightpad.overview-5.3.sentence-1) - [(5.4)](#mdspan.layout.rightpad.overview-5.4) If * [(5.4.1)](#mdspan.layout.rightpad.overview-5.4.1) *rank_* is greater than one, * [(5.4.2)](#mdspan.layout.rightpad.overview-5.4.2) padding_value does not equal dynamic_extent, and * [(5.4.3)](#mdspan.layout.rightpad.overview-5.4.3) extents_type​::​static_extent(k) does not equal dynamic_extent for all k in the range [0, *rank_*), then the product of*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.static_extent(*rank_* - 1)) and all values ext.static_extent(k) with k in the range of [0, *rank_* - 1) is representable as a value of type size_t, and is representable as a value of type index_type[.](#mdspan.layout.rightpad.overview-5.4.sentence-1) #### [23.7.3.4.9.2](#mdspan.layout.rightpad.expo) Exposition-only members [[mdspan.layout.rightpad.expo]](mdspan.layout.rightpad.expo) [🔗](#mdspan.layout.rightpad.expo-itemdecl:1) `static constexpr size_t static-padding-stride = see below; ` [1](#mdspan.layout.rightpad.expo-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23730) The value is - [(1.1)](#mdspan.layout.rightpad.expo-1.1) 0, if *rank_* equals zero or one; - [(1.2)](#mdspan.layout.rightpad.expo-1.2) otherwise, dynamic_extent, if padding_value or *last-static-extent* equalsdynamic_extent; - [(1.3)](#mdspan.layout.rightpad.expo-1.3) otherwise, the size_t value which is*LEAST-MULTIPLE-AT-LEAST*(padding_value, *last-static-extent*)[.](#mdspan.layout.rightpad.expo-1.sentence-1) [🔗](#mdspan.layout.rightpad.expo-itemdecl:2) `index_type stride-rm2 = static-padding-stride; ` [2](#mdspan.layout.rightpad.expo-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23750) *Recommended practice*: Implementations should not store this value if *static-padding-stride* is not dynamic_extent[.](#mdspan.layout.rightpad.expo-2.sentence-1) [*Note [1](#mdspan.layout.rightpad.expo-note-1)*: Using extents instead of index_type as the type of *stride-rm2* would achieve this[.](#mdspan.layout.rightpad.expo-2.sentence-2) — *end note*] #### [23.7.3.4.9.3](#mdspan.layout.rightpad.cons) Constructors [[mdspan.layout.rightpad.cons]](mdspan.layout.rightpad.cons) [🔗](#lib:layout_right_padded::mapping,constructor) `constexpr mapping(const extents_type& ext); ` [1](#mdspan.layout.rightpad.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23769) *Preconditions*: - [(1.1)](#mdspan.layout.rightpad.cons-1.1) The size of the multidimensional index space ext is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-1.1.sentence-1) - [(1.2)](#mdspan.layout.rightpad.cons-1.2) If *rank_* is greater than one andpadding_value does not equal dynamic_extent, then *LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(*rank_* - 1)) is representable as a value of type *index_type*[.](#mdspan.layout.rightpad.cons-1.2.sentence-1) - [(1.3)](#mdspan.layout.rightpad.cons-1.3) If *rank_* is greater than one andpadding_value does not equal dynamic_extent, then the product of*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(*rank_* - 1)) and all values ext.extent(k) with k in the range of [0, *rank_* - 1) is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-1.3.sentence-1) [2](#mdspan.layout.rightpad.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23790) *Effects*: - [(2.1)](#mdspan.layout.rightpad.cons-2.1) Direct-non-list-initializes *extents_* with ext; and - [(2.2)](#mdspan.layout.rightpad.cons-2.2) if *rank_* is greater than one, direct-non-list-initializes *stride-rm2* * [(2.2.1)](#mdspan.layout.rightpad.cons-2.2.1) with ext.extent(*rank_* - 1) if padding_value is dynamic_extent, * [(2.2.2)](#mdspan.layout.rightpad.cons-2.2.2) otherwise with*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(*rank_* - 1))[.](#mdspan.layout.rightpad.cons-2.sentence-1) [🔗](#lib:layout_right_padded::mapping,constructor_) `template constexpr mapping(const extents_type& ext, OtherIndexType pad); ` [3](#mdspan.layout.rightpad.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23816) *Constraints*: - [(3.1)](#mdspan.layout.rightpad.cons-3.1) is_convertible_v is true[.](#mdspan.layout.rightpad.cons-3.1.sentence-1) - [(3.2)](#mdspan.layout.rightpad.cons-3.2) is_nothrow_constructible_v is true[.](#mdspan.layout.rightpad.cons-3.2.sentence-1) [4](#mdspan.layout.rightpad.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23825) *Preconditions*: - [(4.1)](#mdspan.layout.rightpad.cons-4.1) pad is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-4.1.sentence-1) - [(4.2)](#mdspan.layout.rightpad.cons-4.2) extents_type​::​*index-cast*(pad) is greater than zero[.](#mdspan.layout.rightpad.cons-4.2.sentence-1) - [(4.3)](#mdspan.layout.rightpad.cons-4.3) If *rank_* is greater than one, then *LEAST-MULTIPLE-AT-LEAST*(pad, ext.extent(*rank_* - 1)) is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-4.3.sentence-1) - [(4.4)](#mdspan.layout.rightpad.cons-4.4) If *rank_* is greater than one, then the product of*LEAST-MULTIPLE-AT-LEAST*(pad, ext.extent(*rank_* - 1)) and all values ext.extent(k) with k in the range of [0, *rank_* - 1) is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-4.4.sentence-1) - [(4.5)](#mdspan.layout.rightpad.cons-4.5) If padding_value is not equal to dynamic_extent,padding_value equals extents_type​::​*index-cast*(pad)[.](#mdspan.layout.rightpad.cons-4.5.sentence-1) [5](#mdspan.layout.rightpad.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23848) *Effects*: Direct-non-list-initializes *extents_* with ext, and if *rank_* is greater than one, direct-non-list-initializes *stride-rm2* with*LEAST-MULTIPLE-AT-LEAST*(pad, ext.extent(*rank_* - 1))[.](#mdspan.layout.rightpad.cons-5.sentence-1) [🔗](#lib:layout_right_padded::mapping,constructor__) `template constexpr explicit(!is_convertible_v) mapping(const layout_right::mapping& other); ` [6](#mdspan.layout.rightpad.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23864) *Constraints*: is_constructible_v is true[.](#mdspan.layout.rightpad.cons-6.sentence-1) [7](#mdspan.layout.rightpad.cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23868) *Mandates*: If OtherExtents​::​rank() is greater than 1, then(*static-padding-stride* == dynamic_extent) ||(OtherExtents::static_extent(*rank_* - 1) == dynamic_extent) ||(*static-padding-stride* == OtherExtents::static_extent(*rank_* - 1)) is true[.](#mdspan.layout.rightpad.cons-7.sentence-1) [8](#mdspan.layout.rightpad.cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23878) *Preconditions*: - [(8.1)](#mdspan.layout.rightpad.cons-8.1) If *rank_* > 1 is true andpadding_value == dynamic_extent is false, thenother.stride( *rank_* - 2) equals*LEAST-MULTIPLE-AT-LEAST*(padding_value, extents_type::*index-cast*(other.extents().extent(rank_ - 1))) and - [(8.2)](#mdspan.layout.rightpad.cons-8.2) other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-8.sentence-1) [9](#mdspan.layout.rightpad.cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23895) *Effects*: Equivalent to mapping(other.extents())[.](#mdspan.layout.rightpad.cons-9.sentence-1) [🔗](#lib:layout_right_padded::mapping,constructor___) `template constexpr explicit(rank_ > 0) mapping(const layout_stride::mapping& other); ` [10](#mdspan.layout.rightpad.cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23908) *Constraints*: is_constructible_v is true[.](#mdspan.layout.rightpad.cons-10.sentence-1) [11](#mdspan.layout.rightpad.cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23912) *Preconditions*: - [(11.1)](#mdspan.layout.rightpad.cons-11.1) If *rank_* is greater than 1 andpadding_value does not equal dynamic_extent, then other.stride(*rank_* - 2) equals*LEAST-MULTIPLE-AT-LEAST*(padding_value, extents_type::*index-cast*(other.extents().extent(*rank_* - 1))) - [(11.2)](#mdspan.layout.rightpad.cons-11.2) If *rank_* is greater than 0, then other.stride(*rank_* - 1) equals 1[.](#mdspan.layout.rightpad.cons-11.2.sentence-1) - [(11.3)](#mdspan.layout.rightpad.cons-11.3) If *rank_* is greater than 2, then for all r in the range [0, *rank_* - 2),other.stride(r) equals(other.extents().*rev-prod-of-extents*(r) / other.extents().extent(*rank_* - 1)) * other.stride(*rank_* - 2) - [(11.4)](#mdspan.layout.rightpad.cons-11.4) other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-11.4.sentence-1) [12](#mdspan.layout.rightpad.cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23939) *Effects*: - [(12.1)](#mdspan.layout.rightpad.cons-12.1) Direct-non-list-initializes *extents_* with other.extents(); and - [(12.2)](#mdspan.layout.rightpad.cons-12.2) if *rank_* is greater than one, direct-non-list-initializes *stride-rm2* with other.stride(*rank_* - 2)[.](#mdspan.layout.rightpad.cons-12.sentence-1) [🔗](#lib:layout_right_padded::mapping,constructor____) `template constexpr explicit(see below) mapping(const LayoutRightPaddedMapping& other); ` [13](#mdspan.layout.rightpad.cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23959) *Constraints*: - [(13.1)](#mdspan.layout.rightpad.cons-13.1) *is-layout-right-padded-mapping-of* is true[.](#mdspan.layout.rightpad.cons-13.1.sentence-1) - [(13.2)](#mdspan.layout.rightpad.cons-13.2) is_constructible_v is true[.](#mdspan.layout.rightpad.cons-13.2.sentence-1) [14](#mdspan.layout.rightpad.cons-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23970) *Mandates*: If *rank_* is greater than 1, thenpadding_value == dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent || padding_value == LayoutRightPaddedMapping::padding_value is true[.](#mdspan.layout.rightpad.cons-14.sentence-1) [15](#mdspan.layout.rightpad.cons-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23980) *Preconditions*: - [(15.1)](#mdspan.layout.rightpad.cons-15.1) If *rank_* is greater than 1 andpadding_value does not equal dynamic_extent, then other.stride(*rank_* - 2) equals*LEAST-MULTIPLE-AT-LEAST*(padding_value, extents_type::*index-cast*(other.extent(*rank_* - 1))) - [(15.2)](#mdspan.layout.rightpad.cons-15.2) other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-15.sentence-1) [16](#mdspan.layout.rightpad.cons-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23996) *Effects*: - [(16.1)](#mdspan.layout.rightpad.cons-16.1) Direct-non-list-initializes *extents_* with other.extents(); and - [(16.2)](#mdspan.layout.rightpad.cons-16.2) if *rank_* is greater than one, direct-non-list-initializes *stride-rm2* with other.stride(rank_ - 2)[.](#mdspan.layout.rightpad.cons-16.sentence-1) [17](#mdspan.layout.rightpad.cons-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24007) *Remarks*: The expression inside explicit is equivalent to:*rank_* > 1 &&(padding_value != dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent) [🔗](#lib:layout_right_padded::mapping,constructor_____) `template constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping& other) noexcept; ` [18](#mdspan.layout.rightpad.cons-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24025) *Constraints*: - [(18.1)](#mdspan.layout.rightpad.cons-18.1) *is-layout-left-padded-mapping-of* is true or *is-mapping-of* is true[.](#mdspan.layout.rightpad.cons-18.1.sentence-1) - [(18.2)](#mdspan.layout.rightpad.cons-18.2) *rank_* equals zero or one[.](#mdspan.layout.rightpad.cons-18.2.sentence-1) - [(18.3)](#mdspan.layout.rightpad.cons-18.3) is_constructible_v is true[.](#mdspan.layout.rightpad.cons-18.3.sentence-1) [19](#mdspan.layout.rightpad.cons-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24040) *Preconditions*: other.required_span_size() is representable as a value of type index_type[.](#mdspan.layout.rightpad.cons-19.sentence-1) [20](#mdspan.layout.rightpad.cons-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24045) *Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#mdspan.layout.rightpad.cons-20.sentence-1) [21](#mdspan.layout.rightpad.cons-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24049) *Remarks*: The expression inside explicit is equivalent to:!is_convertible_v [*Note [1](#mdspan.layout.rightpad.cons-note-1)*: Neither the input mapping nor the mapping to be constructed uses the padding stride in the rank-0 or rank-1 case, so the padding stride affects neither the constraints nor the preconditions[.](#mdspan.layout.rightpad.cons-21.sentence-1) — *end note*] #### [23.7.3.4.9.4](#mdspan.layout.rightpad.obs) Observers [[mdspan.layout.rightpad.obs]](mdspan.layout.rightpad.obs) [🔗](#lib:layout_right_padded::mapping,strides) `constexpr array strides() const noexcept; ` [1](#mdspan.layout.rightpad.obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24070) *Returns*: array(stride(P_rank)...)[.](#mdspan.layout.rightpad.obs-1.sentence-1) [🔗](#lib:layout_right_padded::mapping,required_span_size) `constexpr index_type required_span_size() const noexcept; ` [2](#mdspan.layout.rightpad.obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24081) *Returns*: 0 if the multidimensional index space *extents_* is empty, otherwise *this(((*extents_*(P_rank) - index_type(1))...)) + 1[.](#mdspan.layout.rightpad.obs-2.sentence-1) [🔗](#lib:layout_right_padded::mapping,operator()) `template constexpr size_t operator()(Indices... idxs) const noexcept; ` [3](#mdspan.layout.rightpad.obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24094) *Constraints*: - [(3.1)](#mdspan.layout.rightpad.obs-3.1) sizeof...(Indices) == *rank_* is true[.](#mdspan.layout.rightpad.obs-3.1.sentence-1) - [(3.2)](#mdspan.layout.rightpad.obs-3.2) (is_convertible_v && ...) is true[.](#mdspan.layout.rightpad.obs-3.2.sentence-1) - [(3.3)](#mdspan.layout.rightpad.obs-3.3) (is_nothrow_constructible_v && ...) is true[.](#mdspan.layout.rightpad.obs-3.3.sentence-1) [4](#mdspan.layout.rightpad.obs-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24105) *Preconditions*: extents_type​::​*index-cast*(idxs) is a multidimensional index in extents() ([[mdspan.overview]](#mdspan.overview "23.7.3.1 Overview"))[.](#mdspan.layout.rightpad.obs-4.sentence-1) [5](#mdspan.layout.rightpad.obs-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24110) *Returns*: ((static_cast(idxs) * stride(P_rank)) + ... + 0)[.](#mdspan.layout.rightpad.obs-5.sentence-1) [🔗](#lib:layout_right_padded::mapping,is_always_exhaustive) `static constexpr bool is_always_exhaustive() noexcept; ` [6](#mdspan.layout.rightpad.obs-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24121) *Returns*: - [(6.1)](#mdspan.layout.rightpad.obs-6.1) If *rank_* equals zero or one, then true; - [(6.2)](#mdspan.layout.rightpad.obs-6.2) otherwise, if neither *static-padding-stride* nor *last-static-extent* equal dynamic_extent, then *static-padding-stride* == *last-static-extent*; - [(6.3)](#mdspan.layout.rightpad.obs-6.3) otherwise, false[.](#mdspan.layout.rightpad.obs-6.sentence-1) [🔗](#lib:layout_right_padded::mapping,is_exhaustive) `constexpr bool is_exhaustive() const noexcept; ` [7](#mdspan.layout.rightpad.obs-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24142) *Returns*: true if *rank_* equals zero or one; otherwise,*extents_*.extent(*rank_* - 1) == stride(*rank_* - 2) [🔗](#mdspan.layout.rightpad.obs-itemdecl:6) `constexpr index_type stride(rank_type r) const noexcept; ` [8](#mdspan.layout.rightpad.obs-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24156) *Preconditions*: r is smaller than *rank_*[.](#mdspan.layout.rightpad.obs-8.sentence-1) [9](#mdspan.layout.rightpad.obs-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24160) *Returns*: - [(9.1)](#mdspan.layout.rightpad.obs-9.1) If r equals *rank_* - 1: 1; - [(9.2)](#mdspan.layout.rightpad.obs-9.2) otherwise, if r equals *rank_* - 2: *stride-rm2*; - [(9.3)](#mdspan.layout.rightpad.obs-9.3) otherwise, the product of *stride-rm2* and all values extents_.extent(k) with k in the range of [r + 1, *rank_* - 1)[.](#mdspan.layout.rightpad.obs-9.sentence-1) [🔗](#lib:layout_right_padded::mapping,operator==) `template friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept; ` [10](#mdspan.layout.rightpad.obs-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24182) *Constraints*: - [(10.1)](#mdspan.layout.rightpad.obs-10.1) *is-layout-right-padded-mapping-of* is true[.](#mdspan.layout.rightpad.obs-10.1.sentence-1) - [(10.2)](#mdspan.layout.rightpad.obs-10.2) LayoutRightPaddedMapping​::​extents_type​::​rank() == *rank_* is true[.](#mdspan.layout.rightpad.obs-10.2.sentence-1) [11](#mdspan.layout.rightpad.obs-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24193) *Returns*: true if x.extents() == y.extents() is true and*rank_* < 2 || x.stride(*rank_* - 2) == y.stride(*rank_* - 2) is true[.](#mdspan.layout.rightpad.obs-11.sentence-1) Otherwise, false[.](#mdspan.layout.rightpad.obs-11.sentence-2) #### [23.7.3.5](#mdspan.accessor) Accessor policy [[mdspan.accessor]](mdspan.accessor) #### [23.7.3.5.1](#mdspan.accessor.general) General [[mdspan.accessor.general]](mdspan.accessor.general) [1](#mdspan.accessor.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24204) An [*accessor policy*](#def:accessor_policy "23.7.3.5.1 General [mdspan.accessor.general]") defines types and operations by which a reference to a single object is created from an abstract data handle to a number of such objects and an index[.](#mdspan.accessor.general-1.sentence-1) [2](#mdspan.accessor.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24209) A range of indices [0,N) is an [*accessible range*](#def:range,accessible "23.7.3.5.1 General [mdspan.accessor.general]") of a given data handle and an accessor if, for each i in the range, the accessor policy's access function produces a valid reference to an object[.](#mdspan.accessor.general-2.sentence-1) [3](#mdspan.accessor.general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24215) In [[mdspan.accessor.reqmts]](#mdspan.accessor.reqmts "23.7.3.5.2 Requirements"), - [(3.1)](#mdspan.accessor.general-3.1) A denotes an accessor policy[.](#mdspan.accessor.general-3.1.sentence-1) - [(3.2)](#mdspan.accessor.general-3.2) a denotes a value of type A or const A[.](#mdspan.accessor.general-3.2.sentence-1) - [(3.3)](#mdspan.accessor.general-3.3) p denotes a value of type A​::​data_handle_type or const A​::​data_handle_type[.](#mdspan.accessor.general-3.3.sentence-1) [*Note [1](#mdspan.accessor.general-note-1)*: The type A​::​data_handle_type need not be dereferenceable[.](#mdspan.accessor.general-3.3.sentence-2) — *end note*] - [(3.4)](#mdspan.accessor.general-3.4) n, i, and j each denote values of type size_t[.](#mdspan.accessor.general-3.4.sentence-1) #### [23.7.3.5.2](#mdspan.accessor.reqmts) Requirements [[mdspan.accessor.reqmts]](mdspan.accessor.reqmts) [1](#mdspan.accessor.reqmts-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24234) A type A meets the accessor policy requirements if - [(1.1)](#mdspan.accessor.reqmts-1.1) A models [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"), - [(1.2)](#mdspan.accessor.reqmts-1.2) is_nothrow_move_constructible_v is true, - [(1.3)](#mdspan.accessor.reqmts-1.3) is_nothrow_move_assignable_v is true, - [(1.4)](#mdspan.accessor.reqmts-1.4) is_nothrow_swappable_v is true, and - [(1.5)](#mdspan.accessor.reqmts-1.5) the following types and expressions are well-formed and have the specified semantics[.](#mdspan.accessor.reqmts-1.sentence-1) [🔗](#mdspan.accessor.reqmts-itemdecl:1) `typename A::element_type ` [2](#mdspan.accessor.reqmts-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24255) *Result*: A complete object type that is not an abstract class type[.](#mdspan.accessor.reqmts-2.sentence-1) [🔗](#mdspan.accessor.reqmts-itemdecl:2) `typename A::data_handle_type ` [3](#mdspan.accessor.reqmts-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24265) *Result*: A type that models [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"), and for which is_nothrow_move_constructible_v is true,is_nothrow_move_assignable_v is true, andis_nothrow_swappable_v is true[.](#mdspan.accessor.reqmts-3.sentence-1) [*Note [1](#mdspan.accessor.reqmts-note-1)*: The type of data_handle_type need not be element_type*[.](#mdspan.accessor.reqmts-3.sentence-2) — *end note*] [🔗](#mdspan.accessor.reqmts-itemdecl:3) `typename A::reference ` [4](#mdspan.accessor.reqmts-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24281) *Result*: A type that models[common_reference_with](concept.commonref#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")[.](#mdspan.accessor.reqmts-4.sentence-1) [*Note [2](#mdspan.accessor.reqmts-note-2)*: The type of reference need not be element_type&[.](#mdspan.accessor.reqmts-4.sentence-2) — *end note*] [🔗](#mdspan.accessor.reqmts-itemdecl:4) `typename A::offset_policy ` [5](#mdspan.accessor.reqmts-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24295) *Result*: A type OP such that: - [(5.1)](#mdspan.accessor.reqmts-5.1) OP meets the accessor policy requirements, - [(5.2)](#mdspan.accessor.reqmts-5.2) [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") is modeled, and - [(5.3)](#mdspan.accessor.reqmts-5.3) is_same_v is true[.](#mdspan.accessor.reqmts-5.sentence-1) [🔗](#mdspan.accessor.reqmts-itemdecl:5) `a.access(p, i) ` [6](#mdspan.accessor.reqmts-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24313) *Result*: A​::​reference [7](#mdspan.accessor.reqmts-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24317) *Remarks*: The expression is equality preserving[.](#mdspan.accessor.reqmts-7.sentence-1) [8](#mdspan.accessor.reqmts-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24321) [*Note [3](#mdspan.accessor.reqmts-note-3)*: Concrete accessor policies can impose preconditions for their access function[.](#mdspan.accessor.reqmts-8.sentence-1) However, they might not[.](#mdspan.accessor.reqmts-8.sentence-2) For example, an accessor wherep is span andaccess(p, i) returns p[i % p.size()] does not need to impose a precondition on i[.](#mdspan.accessor.reqmts-8.sentence-3) — *end note*] [🔗](#mdspan.accessor.reqmts-itemdecl:6) `a.offset(p, i) ` [9](#mdspan.accessor.reqmts-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24337) *Result*: A​::​offset_policy​::​data_handle_type [10](#mdspan.accessor.reqmts-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24341) *Returns*: q such that for b being A​::​offset_policy(a), and any integer n for which [0, n) is an accessible range of p and a: - [(10.1)](#mdspan.accessor.reqmts-10.1) [0,n−i) is an accessible range of q and b; and - [(10.2)](#mdspan.accessor.reqmts-10.2) b.access(q, j) provides access to the same element as a.access(p, i + j), for every j in the range [0,n−i)[.](#mdspan.accessor.reqmts-10.sentence-1) [11](#mdspan.accessor.reqmts-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24355) *Remarks*: The expression is equality-preserving[.](#mdspan.accessor.reqmts-11.sentence-1) #### [23.7.3.5.3](#mdspan.accessor.default) Class template default_accessor [[mdspan.accessor.default]](mdspan.accessor.default) #### [23.7.3.5.3.1](#mdspan.accessor.default.overview) Overview [[mdspan.accessor.default.overview]](mdspan.accessor.default.overview) namespace std {templatestruct default_accessor {using offset_policy = default_accessor; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; constexpr default_accessor() noexcept = default; templateconstexpr default_accessor(default_accessor) noexcept; constexpr reference access(data_handle_type p, size_t i) const noexcept; constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; };} [1](#mdspan.accessor.default.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24382) default_accessor meets the accessor policy requirements[.](#mdspan.accessor.default.overview-1.sentence-1) [2](#mdspan.accessor.default.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24385) ElementType is required to be a complete object type that is neither an abstract class type nor an array type[.](#mdspan.accessor.default.overview-2.sentence-1) [3](#mdspan.accessor.default.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24389) Each specialization of default_accessor is a trivially copyable type that models [semiregular](concepts.object#concept:semiregular "18.6 Object concepts [concepts.object]")[.](#mdspan.accessor.default.overview-3.sentence-1) [4](#mdspan.accessor.default.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24393) [0,n) is an accessible range for an object p of type data_handle_type and an object of type default_accessor if and only if [p, p + n) is a valid range[.](#mdspan.accessor.default.overview-4.sentence-1) #### [23.7.3.5.3.2](#mdspan.accessor.default.members) Members [[mdspan.accessor.default.members]](mdspan.accessor.default.members) [🔗](#lib:default_accessor,constructor) `template constexpr default_accessor(default_accessor) noexcept {} ` [1](#mdspan.accessor.default.members-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24408) *Constraints*: is_convertible_v is true[.](#mdspan.accessor.default.members-1.sentence-1) [🔗](#lib:access,default_accessor) `constexpr reference access(data_handle_type p, size_t i) const noexcept; ` [2](#mdspan.accessor.default.members-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24420) *Effects*: Equivalent to: return p[i]; [🔗](#lib:offset,default_accessor) `constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; ` [3](#mdspan.accessor.default.members-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24431) *Effects*: Equivalent to: return p + i; #### [23.7.3.5.4](#mdspan.accessor.aligned) Class template aligned_accessor [[mdspan.accessor.aligned]](mdspan.accessor.aligned) #### [23.7.3.5.4.1](#mdspan.accessor.aligned.overview) Overview [[mdspan.accessor.aligned.overview]](mdspan.accessor.aligned.overview) namespace std {templatestruct [aligned_accessor](#lib:aligned_accessor "23.7.3.5.4.1 Overview [mdspan.accessor.aligned.overview]") {using offset_policy = default_accessor; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; static constexpr size_t byte_alignment = ByteAlignment; constexpr aligned_accessor() noexcept = default; templateconstexpr aligned_accessor( aligned_accessor) noexcept; templateconstexpr explicit aligned_accessor(default_accessor) noexcept; templateconstexpr operator default_accessor() const noexcept; constexpr reference access(data_handle_type p, size_t i) const noexcept; constexpr typename offset_policy::data_handle_type offset( data_handle_type p, size_t i) const noexcept; };} [1](#mdspan.accessor.aligned.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24469) *Mandates*: - [(1.1)](#mdspan.accessor.aligned.overview-1.1) byte_alignment is a power of two, and - [(1.2)](#mdspan.accessor.aligned.overview-1.2) byte_alignment >= alignof(ElementType) is true[.](#mdspan.accessor.aligned.overview-1.sentence-1) [2](#mdspan.accessor.aligned.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24476) aligned_accessor meets the accessor policy requirements[.](#mdspan.accessor.aligned.overview-2.sentence-1) [3](#mdspan.accessor.aligned.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24479) ElementType is required to be a complete object type that is neither an abstract class type nor an array type[.](#mdspan.accessor.aligned.overview-3.sentence-1) [4](#mdspan.accessor.aligned.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24483) Each specialization of aligned_accessor is a trivially copyable type that models [semiregular](concepts.object#concept:semiregular "18.6 Object concepts [concepts.object]")[.](#mdspan.accessor.aligned.overview-4.sentence-1) [5](#mdspan.accessor.aligned.overview-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24487) [0, n) is an accessible range for an object p of type data_handle_type and an object of type aligned_accessor if and only if - [(5.1)](#mdspan.accessor.aligned.overview-5.1) [p, p + n) is a valid range, and, - [(5.2)](#mdspan.accessor.aligned.overview-5.2) if n is greater than zero, then is_sufficiently_aligned(p) is true[.](#mdspan.accessor.aligned.overview-5.sentence-1) [6](#mdspan.accessor.aligned.overview-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24499) [*Example [1](#mdspan.accessor.aligned.overview-example-1)*: The following function compute uses is_sufficiently_aligned to check whether a given mdspan with default_accessor has a data handle with sufficient alignment to be used with aligned_accessor[.](#mdspan.accessor.aligned.overview-6.sentence-1) If so, the function dispatches to a function compute_using_fourfold_overalignment that requires fourfold over-alignment of arrays, but can therefore use hardware-specific instructions, such as four-wide SIMD (Single Instruction Multiple Data) instructions[.](#mdspan.accessor.aligned.overview-6.sentence-2) Otherwise, compute dispatches to a possibly less optimized function compute_without_requiring_overalignment that has no over-alignment requirement[.](#mdspan.accessor.aligned.overview-6.sentence-3) void compute_using_fourfold_overalignment( std::mdspan, std::layout_right, std::aligned_accessor> x); void compute_without_requiring_overalignment( std::mdspan, std::layout_right> x); void compute(std::mdspan> x) {constexpr auto byte_alignment = 4 * sizeof(float); auto accessor = std::aligned_accessor{}; auto x_handle = x.data_handle(); if (std::is_sufficiently_aligned(x_handle)) { compute_using_fourfold_overalignment(std::mdspan{x_handle, x.mapping(), accessor}); } else { compute_without_requiring_overalignment(x); }} — *end example*] #### [23.7.3.5.4.2](#mdspan.accessor.aligned.members) Members [[mdspan.accessor.aligned.members]](mdspan.accessor.aligned.members) [🔗](#lib:aligned_accessor,constructor) `template constexpr aligned_accessor(aligned_accessor) noexcept; ` [1](#mdspan.accessor.aligned.members-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24545) *Constraints*: - [(1.1)](#mdspan.accessor.aligned.members-1.1) is_convertible_v is true[.](#mdspan.accessor.aligned.members-1.1.sentence-1) - [(1.2)](#mdspan.accessor.aligned.members-1.2) OtherByteAlignment >= byte_alignment is true[.](#mdspan.accessor.aligned.members-1.2.sentence-1) [2](#mdspan.accessor.aligned.members-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24555) *Effects*: None[.](#mdspan.accessor.aligned.members-2.sentence-1) [🔗](#lib:aligned_accessor,constructor_) `template constexpr explicit aligned_accessor(default_accessor) noexcept; ` [3](#mdspan.accessor.aligned.members-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24567) *Constraints*: is_convertible_v is true[.](#mdspan.accessor.aligned.members-3.sentence-1) [4](#mdspan.accessor.aligned.members-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24572) *Effects*: None[.](#mdspan.accessor.aligned.members-4.sentence-1) [🔗](#lib:access,aligned_accessor) `constexpr reference access(data_handle_type p, size_t i) const noexcept; ` [5](#mdspan.accessor.aligned.members-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24583) *Preconditions*: [0, i + 1) is an accessible range for p and *this[.](#mdspan.accessor.aligned.members-5.sentence-1) [6](#mdspan.accessor.aligned.members-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24587) *Effects*: Equivalent to: return assume_aligned(p)[i]; [🔗](#lib:operator_default_accessor,aligned_accessor) `template constexpr operator default_accessor() const noexcept; ` [7](#mdspan.accessor.aligned.members-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24599) *Constraints*: is_convertible_v is true[.](#mdspan.accessor.aligned.members-7.sentence-1) [8](#mdspan.accessor.aligned.members-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24604) *Effects*: Equivalent to: return {}; [🔗](#lib:offset,aligned_accessor) `constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const noexcept; ` [9](#mdspan.accessor.aligned.members-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24616) *Preconditions*: [0, i + 1) is an accessible range for p and *this[.](#mdspan.accessor.aligned.members-9.sentence-1) [10](#mdspan.accessor.aligned.members-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24620) *Effects*: Equivalent to: return assume_aligned(p) + i; #### [23.7.3.6](#mdspan.mdspan) Class template mdspan [[mdspan.mdspan]](mdspan.mdspan) #### [23.7.3.6.1](#mdspan.mdspan.overview) Overview [[mdspan.mdspan.overview]](mdspan.mdspan.overview) [1](#mdspan.mdspan.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24629) mdspan is a view of a multidimensional array of elements[.](#mdspan.mdspan.overview-1.sentence-1) namespace std {template>class mdspan {public:using extents_type = Extents; using layout_type = LayoutPolicy; using accessor_type = AccessorPolicy; using mapping_type = typename layout_type::template mapping; using element_type = ElementType; using value_type = remove_cv_t; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using data_handle_type = typename accessor_type::data_handle_type; using reference = typename accessor_type::reference; static constexpr rank_type rank() noexcept { return extents_type::rank(); }static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }static constexpr size_t static_extent(rank_type r) noexcept{ return extents_type::static_extent(r); }constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); }// [[mdspan.mdspan.cons]](#mdspan.mdspan.cons "23.7.3.6.2 Constructors"), constructorsconstexpr mdspan(); constexpr mdspan(const mdspan& rhs) = default; constexpr mdspan(mdspan&& rhs) = default; templateconstexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts); templateconstexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span exts); templateconstexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array& exts); constexpr mdspan(data_handle_type p, const extents_type& ext); constexpr mdspan(data_handle_type p, const mapping_type& m); constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); templateconstexpr explicit(*see below*) mdspan(const mdspan& other); constexpr mdspan& operator=(const mdspan& rhs) = default; constexpr mdspan& operator=(mdspan&& rhs) = default; // [[mdspan.mdspan.members]](#mdspan.mdspan.members "23.7.3.6.3 Members"), memberstemplateconstexpr reference operator[](OtherIndexTypes... indices) const; templateconstexpr reference operator[](span indices) const; templateconstexpr reference operator[](const array& indices) const; templateconstexpr reference at(OtherIndexTypes... indices) const; // freestanding-deletedtemplateconstexpr reference at(span indices) const; // freestanding-deletedtemplateconstexpr reference at(const array& indices) const; // freestanding-deletedconstexpr size_type size() const noexcept; constexpr bool empty() const noexcept; friend constexpr void swap(mdspan& x, mdspan& y) noexcept; constexpr const extents_type& extents() const noexcept { return *map_*.extents(); }constexpr const data_handle_type& data_handle() const noexcept { return *ptr_*; }constexpr const mapping_type& mapping() const noexcept { return *map_*; }constexpr const accessor_type& accessor() const noexcept { return *acc_*; }static constexpr bool is_always_unique(){ return mapping_type::is_always_unique(); }static constexpr bool is_always_exhaustive(){ return mapping_type::is_always_exhaustive(); }static constexpr bool is_always_strided(){ return mapping_type::is_always_strided(); }constexpr bool is_unique() const{ return *map_*.is_unique(); }constexpr bool is_exhaustive() const{ return *map_*.is_exhaustive(); }constexpr bool is_strided() const{ return *map_*.is_strided(); }constexpr index_type stride(rank_type r) const{ return *map_*.stride(r); }private: accessor_type *acc_*; // *exposition only* mapping_type *map_*; // *exposition only* data_handle_type *ptr_*; // *exposition only*}; templaterequires (is_array_v && rank_v == 1) mdspan(CArray&)-> mdspan, extents>>; templaterequires (is_pointer_v>) mdspan(Pointer&&)-> mdspan>, extents>; templaterequires ((is_convertible_v && ...) && sizeof...(Integrals) > 0)explicit mdspan(ElementType*, Integrals...)-> mdspan synopsis [span.syn]")...>>; template mdspan(ElementType*, span)-> mdspan>; template mdspan(ElementType*, const array&)-> mdspan>; template mdspan(ElementType*, const extents&)-> mdspan>; template mdspan(ElementType*, const MappingType&)-> mdspan; template mdspan(const typename AccessorType::data_handle_type&, const MappingType&, const AccessorType&)-> mdspan;} [2](#mdspan.mdspan.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24772) *Mandates*: - [(2.1)](#mdspan.mdspan.overview-2.1) ElementType is a complete object type that is neither an abstract class type nor an array type, - [(2.2)](#mdspan.mdspan.overview-2.2) Extents is a specialization of extents, and - [(2.3)](#mdspan.mdspan.overview-2.3) is_same_v is true[.](#mdspan.mdspan.overview-2.sentence-1) [3](#mdspan.mdspan.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24785) LayoutPolicy shall meet the layout mapping policy requirements ([[mdspan.layout.policy.reqmts]](#mdspan.layout.policy.reqmts "23.7.3.4.3 Layout mapping policy requirements")), andAccessorPolicy shall meet the accessor policy requirements ([[mdspan.accessor.reqmts]](#mdspan.accessor.reqmts "23.7.3.5.2 Requirements"))[.](#mdspan.mdspan.overview-3.sentence-1) [4](#mdspan.mdspan.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24791) Each specialization MDS of mdspan models [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]") and - [(4.1)](#mdspan.mdspan.overview-4.1) is_nothrow_move_constructible_v is true, - [(4.2)](#mdspan.mdspan.overview-4.2) is_nothrow_move_assignable_v is true, and - [(4.3)](#mdspan.mdspan.overview-4.3) is_nothrow_swappable_v is true[.](#mdspan.mdspan.overview-4.sentence-1) [5](#mdspan.mdspan.overview-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24802) A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_type are trivially copyable types[.](#mdspan.mdspan.overview-5.sentence-1) #### [23.7.3.6.2](#mdspan.mdspan.cons) Constructors [[mdspan.mdspan.cons]](mdspan.mdspan.cons) [🔗](#lib:mdspan,constructor) `constexpr mdspan(); ` [1](#mdspan.mdspan.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24815) *Constraints*: - [(1.1)](#mdspan.mdspan.cons-1.1) rank_dynamic() > 0 is true[.](#mdspan.mdspan.cons-1.1.sentence-1) - [(1.2)](#mdspan.mdspan.cons-1.2) is_default_constructible_v is true[.](#mdspan.mdspan.cons-1.2.sentence-1) - [(1.3)](#mdspan.mdspan.cons-1.3) is_default_constructible_v is true[.](#mdspan.mdspan.cons-1.3.sentence-1) - [(1.4)](#mdspan.mdspan.cons-1.4) is_default_constructible_v is true[.](#mdspan.mdspan.cons-1.4.sentence-1) [2](#mdspan.mdspan.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24828) *Preconditions*: [0, *map_*.required_span_size()) is an accessible range of *ptr_* and *acc_* for the values of *map_* and *acc_* after the invocation of this constructor[.](#mdspan.mdspan.cons-2.sentence-1) [3](#mdspan.mdspan.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24835) *Effects*: Value-initializes *ptr_*, *map_*, and *acc_*[.](#mdspan.mdspan.cons-3.sentence-1) [🔗](#lib:mdspan,constructor_) `template constexpr explicit mdspan(data_handle_type p, OtherIndexTypes... exts); ` [4](#mdspan.mdspan.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24847) Let N be sizeof...(OtherIndexTypes)[.](#mdspan.mdspan.cons-4.sentence-1) [5](#mdspan.mdspan.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24850) *Constraints*: - [(5.1)](#mdspan.mdspan.cons-5.1) (is_convertible_v && ...) is true, - [(5.2)](#mdspan.mdspan.cons-5.2) (is_nothrow_constructible && ...) is true, - [(5.3)](#mdspan.mdspan.cons-5.3) N == rank() || N == rank_dynamic() is true, - [(5.4)](#mdspan.mdspan.cons-5.4) is_constructible_v is true, and - [(5.5)](#mdspan.mdspan.cons-5.5) is_default_constructible_v is true[.](#mdspan.mdspan.cons-5.sentence-1) [6](#mdspan.mdspan.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24865) *Preconditions*: [0, *map_*.required_span_size()) is an accessible range of p and *acc_* for the values of *map_* and *acc_* after the invocation of this constructor[.](#mdspan.mdspan.cons-6.sentence-1) [7](#mdspan.mdspan.cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24872) *Effects*: - [(7.1)](#mdspan.mdspan.cons-7.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(7.2)](#mdspan.mdspan.cons-7.2) direct-non-list-initializes *map_* withextents_type(static_cast(std​::​move(exts​))...), and - [(7.3)](#mdspan.mdspan.cons-7.3) value-initializes *acc_*[.](#mdspan.mdspan.cons-7.sentence-1) [🔗](#lib:mdspan,constructor__) `template constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span exts); template constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array& exts); ` [8](#mdspan.mdspan.cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24896) *Constraints*: - [(8.1)](#mdspan.mdspan.cons-8.1) is_convertible_v is true, - [(8.2)](#mdspan.mdspan.cons-8.2) is_nothrow_constructible_v is true, - [(8.3)](#mdspan.mdspan.cons-8.3) N == rank() || N == rank_dynamic() is true, - [(8.4)](#mdspan.mdspan.cons-8.4) is_constructible_v is true, and - [(8.5)](#mdspan.mdspan.cons-8.5) is_default_constructible_v is true[.](#mdspan.mdspan.cons-8.sentence-1) [9](#mdspan.mdspan.cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24911) *Preconditions*: [0, *map_*.required_span_size()) is an accessible range of p and *acc_* for the values of *map_* and *acc_* after the invocation of this constructor[.](#mdspan.mdspan.cons-9.sentence-1) [10](#mdspan.mdspan.cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24918) *Effects*: - [(10.1)](#mdspan.mdspan.cons-10.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(10.2)](#mdspan.mdspan.cons-10.2) direct-non-list-initializes *map_* with extents_type(exts), and - [(10.3)](#mdspan.mdspan.cons-10.3) value-initializes *acc_*[.](#mdspan.mdspan.cons-10.sentence-1) [🔗](#lib:mdspan,constructor___) `constexpr mdspan(data_handle_type p, const extents_type& ext); ` [11](#mdspan.mdspan.cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24936) *Constraints*: - [(11.1)](#mdspan.mdspan.cons-11.1) is_constructible_v is true, and - [(11.2)](#mdspan.mdspan.cons-11.2) is_default_constructible_v is true[.](#mdspan.mdspan.cons-11.sentence-1) [12](#mdspan.mdspan.cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24945) *Preconditions*: [0, *map_*.required_span_size()) is an accessible range of p and *acc_* for the values of *map_* and *acc_* after the invocation of this constructor[.](#mdspan.mdspan.cons-12.sentence-1) [13](#mdspan.mdspan.cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24952) *Effects*: - [(13.1)](#mdspan.mdspan.cons-13.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(13.2)](#mdspan.mdspan.cons-13.2) direct-non-list-initializes *map_* with ext, and - [(13.3)](#mdspan.mdspan.cons-13.3) value-initializes *acc_*[.](#mdspan.mdspan.cons-13.sentence-1) [🔗](#lib:mdspan,constructor____) `constexpr mdspan(data_handle_type p, const mapping_type& m); ` [14](#mdspan.mdspan.cons-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24970) *Constraints*: is_default_constructible_v is true[.](#mdspan.mdspan.cons-14.sentence-1) [15](#mdspan.mdspan.cons-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24974) *Preconditions*: [0, m.required_span_size()) is an accessible range of p and *acc_* for the value of *acc_* after the invocation of this constructor[.](#mdspan.mdspan.cons-15.sentence-1) [16](#mdspan.mdspan.cons-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24980) *Effects*: - [(16.1)](#mdspan.mdspan.cons-16.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(16.2)](#mdspan.mdspan.cons-16.2) direct-non-list-initializes *map_* with m, and - [(16.3)](#mdspan.mdspan.cons-16.3) value-initializes *acc_*[.](#mdspan.mdspan.cons-16.sentence-1) [🔗](#lib:mdspan,constructor_____) `constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); ` [17](#mdspan.mdspan.cons-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24998) *Preconditions*: [0, m.required_span_size()) is an accessible range of p and a[.](#mdspan.mdspan.cons-17.sentence-1) [18](#mdspan.mdspan.cons-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25003) *Effects*: - [(18.1)](#mdspan.mdspan.cons-18.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(18.2)](#mdspan.mdspan.cons-18.2) direct-non-list-initializes *map_* with m, and - [(18.3)](#mdspan.mdspan.cons-18.3) direct-non-list-initializes *acc_* with a[.](#mdspan.mdspan.cons-18.sentence-1) [🔗](#lib:mdspan,constructor______) `template constexpr explicit(see below) mdspan(const mdspan& other); ` [19](#mdspan.mdspan.cons-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25025) *Constraints*: - [(19.1)](#mdspan.mdspan.cons-19.1) is_constructible_v&> is true, and - [(19.2)](#mdspan.mdspan.cons-19.2) is_constructible_v is true[.](#mdspan.mdspan.cons-19.sentence-1) [20](#mdspan.mdspan.cons-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25035) *Mandates*: - [(20.1)](#mdspan.mdspan.cons-20.1) is_constructible_v is true, and - [(20.2)](#mdspan.mdspan.cons-20.2) is_constructible_v is true[.](#mdspan.mdspan.cons-20.sentence-1) [21](#mdspan.mdspan.cons-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25044) *Preconditions*: [0, *map_*.required_span_size()) is an accessible range of *ptr_* and *acc_* for values of *ptr_*, *map_*, and *acc_* after the invocation of this constructor[.](#mdspan.mdspan.cons-21.sentence-1) [22](#mdspan.mdspan.cons-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25051) *Hardened preconditions*: For each rank index r of extents_type,static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r) is true[.](#mdspan.mdspan.cons-22.sentence-1) [23](#mdspan.mdspan.cons-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25057) *Effects*: - [(23.1)](#mdspan.mdspan.cons-23.1) Direct-non-list-initializes *ptr_* with other.*ptr_*, - [(23.2)](#mdspan.mdspan.cons-23.2) direct-non-list-initializes *map_* with other.*map_*, and - [(23.3)](#mdspan.mdspan.cons-23.3) direct-non-list-initializes *acc_* with other.*acc_*[.](#mdspan.mdspan.cons-23.sentence-1) [24](#mdspan.mdspan.cons-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25068) *Remarks*: The expression inside explicit is equivalent to:!is_convertible_v&, mapping_type>|| !is_convertible_v #### [23.7.3.6.3](#mdspan.mdspan.members) Members [[mdspan.mdspan.members]](mdspan.mdspan.members) [🔗](#lib:operator%5b%5d,mdspan) `template constexpr reference operator[](OtherIndexTypes... indices) const; ` [1](#mdspan.mdspan.members-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25086) *Constraints*: - [(1.1)](#mdspan.mdspan.members-1.1) (is_convertible_v && ...) is true, - [(1.2)](#mdspan.mdspan.members-1.2) (is_nothrow_constructible_v && ...) is true, and - [(1.3)](#mdspan.mdspan.members-1.3) sizeof...(OtherIndexTypes) == rank() is true[.](#mdspan.mdspan.members-1.sentence-1) [2](#mdspan.mdspan.members-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25097) Let I be extents_type​::​*index-cast*(std​::​move(indices))[.](#mdspan.mdspan.members-2.sentence-1) [3](#mdspan.mdspan.members-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25100) *Hardened preconditions*: I is a multidimensional index in extents()[.](#mdspan.mdspan.members-3.sentence-1) [*Note [1](#mdspan.mdspan.members-note-1)*: This implies that*map_*(I) < *map_*.required_span_size() is true[.](#mdspan.mdspan.members-3.sentence-2) — *end note*] [4](#mdspan.mdspan.members-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25109) *Effects*: Equivalent to:return *acc_*.access(*ptr_*, *map_*(static_cast(std::move(indices))...)); [🔗](#lib:operator%5b%5d,mdspan_) `template constexpr reference operator[](span indices) const; template constexpr reference operator[](const array& indices) const; ` [5](#mdspan.mdspan.members-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25126) *Constraints*: - [(5.1)](#mdspan.mdspan.members-5.1) is_convertible_v is true, and - [(5.2)](#mdspan.mdspan.members-5.2) is_nothrow_constructible_v is true[.](#mdspan.mdspan.members-5.sentence-1) [6](#mdspan.mdspan.members-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25135) *Effects*: Let P be a parameter pack such thatis_same_v, index_sequence> is true[.](#mdspan.mdspan.members-6.sentence-1) Equivalent to:return operator[](extents_type::*index-cast*(as_const(indices[P]))...); [🔗](#lib:at,mdspan) `template constexpr reference at(OtherIndexTypes... indices) const; ` [7](#mdspan.mdspan.members-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25155) *Constraints*: - [(7.1)](#mdspan.mdspan.members-7.1) (is_convertible_v && ...) is true, - [(7.2)](#mdspan.mdspan.members-7.2) (is_nothrow_constructible_v && ...) is true, and - [(7.3)](#mdspan.mdspan.members-7.3) sizeof...(OtherIndexTypes) == rank() is true[.](#mdspan.mdspan.members-7.sentence-1) [8](#mdspan.mdspan.members-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25166) Let I be extents_type​::​*index-cast*(std​::​move(indices))[.](#mdspan.mdspan.members-8.sentence-1) [9](#mdspan.mdspan.members-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25169) *Returns*: (*this)[I...][.](#mdspan.mdspan.members-9.sentence-1) [10](#mdspan.mdspan.members-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25173) *Throws*: out_of_range if I is not a multidimensional index in extents()[.](#mdspan.mdspan.members-10.sentence-1) [🔗](#lib:at,mdspan_) `template constexpr reference at(span indices) const; template constexpr reference at(const array& indices) const; ` [11](#mdspan.mdspan.members-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25187) *Constraints*: - [(11.1)](#mdspan.mdspan.members-11.1) is_convertible_v is true, and - [(11.2)](#mdspan.mdspan.members-11.2) is_nothrow_constructible_v is true[.](#mdspan.mdspan.members-11.sentence-1) [12](#mdspan.mdspan.members-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25196) *Effects*: Let P be a parameter pack such thatis_same_v, index_sequence> is true[.](#mdspan.mdspan.members-12.sentence-1) Equivalent to:return at(extents_type::*index-cast*(as_const(indices[P]))...); [🔗](#lib:size,mdspan) `constexpr size_type size() const noexcept; ` [13](#mdspan.mdspan.members-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25215) *Preconditions*: The size of the multidimensional index space extents() is representable as a value of type size_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#mdspan.mdspan.members-13.sentence-1) [14](#mdspan.mdspan.members-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25220) *Returns*: extents().*fwd-prod-of-extents*(rank())[.](#mdspan.mdspan.members-14.sentence-1) [🔗](#lib:empty,mdspan) `constexpr bool empty() const noexcept; ` [15](#mdspan.mdspan.members-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25231) *Returns*: true if the size of the multidimensional index space extents() is 0, otherwise false[.](#mdspan.mdspan.members-15.sentence-1) [🔗](#lib:swap,mdspan) `friend constexpr void swap(mdspan& x, mdspan& y) noexcept; ` [16](#mdspan.mdspan.members-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25244) *Effects*: Equivalent to:swap(x.*ptr_*, y.*ptr_*); swap(x.*map_*, y.*map_*); swap(x.*acc_*, y.*acc_*); #### [23.7.3.7](#mdspan.sub) submdspan [[mdspan.sub]](mdspan.sub) #### [23.7.3.7.1](#mdspan.sub.overview) Overview [[mdspan.sub.overview]](mdspan.sub.overview) [1](#mdspan.sub.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25258) The submdspan facilities create a new mdspan viewing a subset of elements of an existing input mdspan[.](#mdspan.sub.overview-1.sentence-1) The subset viewed by the created mdspan is determined by the SliceSpecifier arguments[.](#mdspan.sub.overview-1.sentence-2) [2](#mdspan.sub.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25264) For each function defined in [[mdspan.sub]](#mdspan.sub "23.7.3.7 submdspan") that takes a parameter pack named slices as an argument: - [(2.1)](#mdspan.sub.overview-2.1) let index_type be * [(2.1.1)](#mdspan.sub.overview-2.1.1) M​::​index_type if the function is a member of a class M, * [(2.1.2)](#mdspan.sub.overview-2.1.2) otherwise, remove_reference_t​::​index_type if the function has a parameter named src, * [(2.1.3)](#mdspan.sub.overview-2.1.3) otherwise, the same type as the function's template argument IndexType; - [(2.2)](#mdspan.sub.overview-2.2) let rank be the number of elements in slices; - [(2.3)](#mdspan.sub.overview-2.3) let sk be the kth element of slices; - [(2.4)](#mdspan.sub.overview-2.4) let Sk be the type of sk; and - [(2.5)](#mdspan.sub.overview-2.5) let *map-rank* be an array such that for each k in the range [0, rank),*map-rank*[k] equals: * [(2.5.1)](#mdspan.sub.overview-2.5.1) dynamic_extent if Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), * [(2.5.2)](#mdspan.sub.overview-2.5.2) otherwise, the number of types Sj with j[.](#mdspan.sub.overview-2.sentence-1) #### [23.7.3.7.2](#mdspan.sub.strided.slice) strided_slice [[mdspan.sub.strided.slice]](mdspan.sub.strided.slice) [1](#mdspan.sub.strided.slice-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25300) strided_slice represents a set ofextent regularly spaced integer indices[.](#mdspan.sub.strided.slice-1.sentence-1) The indices start at offset, and increase by increments of stride[.](#mdspan.sub.strided.slice-1.sentence-2) [🔗](#lib:strided_slice) namespace std {templatestruct strided_slice {using offset_type = OffsetType; using extent_type = ExtentType; using stride_type = StrideType; [[no_unique_address]] offset_type offset{}; [[no_unique_address]] extent_type extent{}; [[no_unique_address]] stride_type stride{}; };} [2](#mdspan.sub.strided.slice-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25322) strided_slice has the data members and special members specified above[.](#mdspan.sub.strided.slice-2.sentence-1) It has no base classes or members other than those specified[.](#mdspan.sub.strided.slice-2.sentence-2) [3](#mdspan.sub.strided.slice-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25326) *Mandates*: OffsetType, ExtentType, and StrideType are signed or unsigned integer types, or model [*integral-constant-like*](#concept:integral-constant-like "23.7.2.1 Header synopsis [span.syn]")[.](#mdspan.sub.strided.slice-3.sentence-1) [*Note [1](#mdspan.sub.strided.slice-note-1)*: strided_slice{.offset = 1, .extent = 10, .stride = 3} indicates the indices 1, 4, 7, and 10[.](#mdspan.sub.strided.slice-3.sentence-2) Indices are selected from the half-open interval [1, 1 + 10)[.](#mdspan.sub.strided.slice-3.sentence-3) — *end note*] #### [23.7.3.7.3](#mdspan.sub.map.result) submdspan_mapping_result [[mdspan.sub.map.result]](mdspan.sub.map.result) [1](#mdspan.sub.map.result-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25339) Specializations of submdspan_mapping_result are returned by overloads of submdspan_mapping[.](#mdspan.sub.map.result-1.sentence-1) [🔗](#lib:submdspan_mapping_result) namespace std {templatestruct submdspan_mapping_result {[[no_unique_address]] LayoutMapping mapping = LayoutMapping(); size_t offset{}; };} [2](#mdspan.sub.map.result-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25354) submdspan_mapping_result has the data members and special members specified above[.](#mdspan.sub.map.result-2.sentence-1) It has no base classes or members other than those specified[.](#mdspan.sub.map.result-2.sentence-2) [3](#mdspan.sub.map.result-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25359) LayoutMapping shall meet the layout mapping requirements ([[mdspan.layout.policy.reqmts]](#mdspan.layout.policy.reqmts "23.7.3.4.3 Layout mapping policy requirements"))[.](#mdspan.sub.map.result-3.sentence-1) #### [23.7.3.7.4](#mdspan.sub.helpers) Exposition-only helpers [[mdspan.sub.helpers]](mdspan.sub.helpers) [🔗](#lib:de-ice) `template constexpr T de-ice(T val) { return val; } template<[integral-constant-like](#concept:integral-constant-like "23.7.2.1 Header synopsis [span.syn]") T> constexpr auto de-ice(T) { return T::value; } template constexpr IndexType first_(SliceSpecifiers... slices); ` [1](#mdspan.sub.helpers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25378) *Mandates*: IndexType is a signed or unsigned integer type[.](#mdspan.sub.helpers-1.sentence-1) [2](#mdspan.sub.helpers-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25383) Let ϕk denote the following value: - [(2.1)](#mdspan.sub.helpers-2.1) sk if Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); - [(2.2)](#mdspan.sub.helpers-2.2) otherwise,get<0>(sk) if Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2 Header synopsis [mdspan.syn]"); - [(2.3)](#mdspan.sub.helpers-2.3) otherwise,*de-ice*(sk.offset) if Sk is a specialization of strided_slice; - [(2.4)](#mdspan.sub.helpers-2.4) otherwise,0[.](#mdspan.sub.helpers-2.sentence-1) [3](#mdspan.sub.helpers-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25401) *Preconditions*: ϕk is representable as a value of type IndexType[.](#mdspan.sub.helpers-3.sentence-1) [4](#mdspan.sub.helpers-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25405) *Returns*: extents​::​*index-cast*(ϕk)[.](#mdspan.sub.helpers-4.sentence-1) [🔗](#lib:last_) `template constexpr auto last_(const Extents& src, SliceSpecifiers... slices); ` [5](#mdspan.sub.helpers-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25417) *Mandates*: Extents is a specialization of extents[.](#mdspan.sub.helpers-5.sentence-1) [6](#mdspan.sub.helpers-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25421) Let index_type be typename Extents​::​index_type[.](#mdspan.sub.helpers-6.sentence-1) [7](#mdspan.sub.helpers-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25425) Let λk denote the following value: - [(7.1)](#mdspan.sub.helpers-7.1) *de-ice*(sk) + 1 if Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); otherwise - [(7.2)](#mdspan.sub.helpers-7.2) get<1>(sk) if Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2 Header synopsis [mdspan.syn]"); otherwise - [(7.3)](#mdspan.sub.helpers-7.3) *de-ice*(sk.offset) +*de-ice*(sk.extent) if Sk is a specialization of strided_slice; otherwise - [(7.4)](#mdspan.sub.helpers-7.4) src.extent(k)[.](#mdspan.sub.helpers-7.sentence-1) [8](#mdspan.sub.helpers-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25443) *Preconditions*: λk is representable as a value of type index_type[.](#mdspan.sub.helpers-8.sentence-1) [9](#mdspan.sub.helpers-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25447) *Returns*: Extents​::​*index-cast*(λk)[.](#mdspan.sub.helpers-9.sentence-1) [🔗](#lib:src-indices) `template constexpr array src-indices(const array& indices, SliceSpecifiers... slices); ` [10](#mdspan.sub.helpers-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25460) *Mandates*: IndexType is a signed or unsigned integer type[.](#mdspan.sub.helpers-10.sentence-1) [11](#mdspan.sub.helpers-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25464) *Returns*: An array src_idx such that for each k in the range [0, sizeof...(SliceSpecifiers)),src_idx[k] equals - [(11.1)](#mdspan.sub.helpers-11.1) *first_*(slices...) for each k where *map-rank*[k] equalsdynamic_extent, - [(11.2)](#mdspan.sub.helpers-11.2) otherwise,*first_*(slices...) +indices[*map-rank*[k]]. #### [23.7.3.7.5](#mdspan.sub.extents) submdspan_extents function [[mdspan.sub.extents]](mdspan.sub.extents) [🔗](#lib:submdspan_extents) `template constexpr auto submdspan_extents(const extents& src, SliceSpecifiers... slices); ` [1](#mdspan.sub.extents-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25496) *Constraints*: sizeof...(slices) equals sizeof...(Extents)[.](#mdspan.sub.extents-1.sentence-1) [2](#mdspan.sub.extents-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25500) *Mandates*: For each rank index k of src.extents(), exactly one of the following is true: - [(2.1)](#mdspan.sub.extents-2.1) Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), - [(2.2)](#mdspan.sub.extents-2.2) Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2 Header synopsis [mdspan.syn]"), - [(2.3)](#mdspan.sub.extents-2.3) is_convertible_v is true, or - [(2.4)](#mdspan.sub.extents-2.4) Sk is a specialization of strided_slice[.](#mdspan.sub.extents-2.sentence-1) [3](#mdspan.sub.extents-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25511) *Preconditions*: For each rank index k of src.extents(), all of the following are true: - [(3.1)](#mdspan.sub.extents-3.1) if Sk is a specialization of strided_slice * [(3.1.1)](#mdspan.sub.extents-3.1.1) sk.extent=0, or * [(3.1.2)](#mdspan.sub.extents-3.1.2) sk.stride>0 - [(3.2)](#mdspan.sub.extents-3.2) 0 ≤ *first_*(slices...) ≤ *last_*(src, slices...) ≤ src.extent(k) [4](#mdspan.sub.extents-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25528) Let SubExtents be a specialization of extents such that: - [(4.1)](#mdspan.sub.extents-4.1) SubExtents​::​rank() equals the number of k such thatSk does not model [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); and - [(4.2)](#mdspan.sub.extents-4.2) for each rank index k of Extents such that*map-rank*[k] != dynamic_extent is true,SubExtents​::​static_extent(*map-rank*[k]) equals: * [(4.2.1)](#mdspan.sub.extents-4.2.1) Extents​::​static_extent(k) if is_convertible_v is true; otherwise * [(4.2.2)](#mdspan.sub.extents-4.2.2) *de-ice*(tuple_element_t<1, Sk>()) -*de-ice*(tuple_element_t<0, Sk>()) if Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2 Header synopsis [mdspan.syn]"), and both tuple_element_t<0, Sk> and tuple_element_t<1, Sk> model [*integral-constant-like*](#concept:integral-constant-like "23.7.2.1 Header synopsis [span.syn]"); otherwise * [(4.2.3)](#mdspan.sub.extents-4.2.3) 0, if Sk is a specialization of strided_slice, whose extent_type models *integral-constant-like*, for which extent_type() equals zero; otherwise * [(4.2.4)](#mdspan.sub.extents-4.2.4) 1 + (*de-ice*(Sk​::​extent_type()) - 1) /*de-ice*(Sk​::​stride_type()), if Sk is a specialization of strided_slice whose extent_type and stride_type model *integral-constant-like*; * [(4.2.5)](#mdspan.sub.extents-4.2.5) otherwise, dynamic_extent[.](#mdspan.sub.extents-4.sentence-1) [5](#mdspan.sub.extents-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25573) *Returns*: A value ext of type SubExtents such that for each k for which *map-rank*[k] != dynamic_extent is true,ext.extent(*map-rank*[k]) equals: - [(5.1)](#mdspan.sub.extents-5.1) sk.extent == 0 ? 0 : 1 + (*de-ice*(sk.extent) - 1) / *de-ice*(sk.stride) if Sk is a specialization of strided_slice, - [(5.2)](#mdspan.sub.extents-5.2) otherwise,*last_*(src, slices...) - *first_*(slices...)[.](#mdspan.sub.extents-5.sentence-1) #### [23.7.3.7.6](#mdspan.sub.map) Specializations of submdspan_mapping [[mdspan.sub.map]](mdspan.sub.map) #### [23.7.3.7.6.1](#mdspan.sub.map.common) Common [[mdspan.sub.map.common]](mdspan.sub.map.common) [1](#mdspan.sub.map.common-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25594) The following elements apply to all functions in [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6 Specializations of submdspan_­mapping")[.](#mdspan.sub.map.common-1.sentence-1) [2](#mdspan.sub.map.common-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25597) *Constraints*: sizeof...(slices) equals extents_type​::​rank()[.](#mdspan.sub.map.common-2.sentence-1) [3](#mdspan.sub.map.common-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25601) *Mandates*: For each rank index k of extents(), exactly one of the following is true: - [(3.1)](#mdspan.sub.map.common-3.1) Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), - [(3.2)](#mdspan.sub.map.common-3.2) Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2 Header synopsis [mdspan.syn]"), - [(3.3)](#mdspan.sub.map.common-3.3) is_convertible_v is true, or - [(3.4)](#mdspan.sub.map.common-3.4) Sk is a specialization of strided_slice[.](#mdspan.sub.map.common-3.sentence-1) [4](#mdspan.sub.map.common-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25616) *Preconditions*: For each rank index k of extents(), all of the following are true: - [(4.1)](#mdspan.sub.map.common-4.1) if Sk is a specialization of strided_slice,sk.extent is equal to zero orsk.stride is greater than zero; and - [(4.2)](#mdspan.sub.map.common-4.2) 0 ≤ *first_*(slices...) 0 ≤ *last_*(extents(), slices...) 0 ≤ extents().extent(k) [5](#mdspan.sub.map.common-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25631) Let sub_ext be the result of submdspan_extents(extents(), slices...) and let SubExtents be decltype(sub_ext)[.](#mdspan.sub.map.common-5.sentence-1) [6](#mdspan.sub.map.common-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25636) Let sub_strides be an array such that for each rank index k of extents() for which *map-rank*[k] is not dynamic_extent,sub_strides[*map-rank*[k]] equals: - [(6.1)](#mdspan.sub.map.common-6.1) stride(k) * *de-ice*(sk.stride) if Sk is a specialization of strided_slice andsk.stride < sk.extent is true; - [(6.2)](#mdspan.sub.map.common-6.2) otherwise, stride(k)[.](#mdspan.sub.map.common-6.sentence-1) [7](#mdspan.sub.map.common-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25651) Let P be a parameter pack such that is_same_v, index_sequence> is true[.](#mdspan.sub.map.common-7.sentence-1) [8](#mdspan.sub.map.common-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25656) If *first_*(slices...) equals extents().extent(k) for any rank index k of extents(), then let offset be a value of type size_t equal to(*this).required_span_size()[.](#mdspan.sub.map.common-8.sentence-1) Otherwise, let offset be a value of type size_t equal to(*this)(*first_*(slices...)...)[.](#mdspan.sub.map.common-8.sentence-2) [9](#mdspan.sub.map.common-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25666) Given a layout mapping type M, a type S is a[*unit-stride slice for M*](#def:slice,unit-stride "23.7.3.7.6.1 Common [mdspan.sub.map.common]") if - [(9.1)](#mdspan.sub.map.common-9.1) S is a specialization of strided_slice where S​::​stride_type models [*integral-constant-like*](#concept:integral-constant-like "23.7.2.1 Header synopsis [span.syn]") and S​::​stride_type​::​value equals 1, - [(9.2)](#mdspan.sub.map.common-9.2) S models [*index-pair-like*](#concept:index-pair-like "23.7.3.2 Header synopsis [mdspan.syn]"), or - [(9.3)](#mdspan.sub.map.common-9.3) is_convertible_v is true[.](#mdspan.sub.map.common-9.sentence-1) #### [23.7.3.7.6.2](#mdspan.sub.map.left) layout_left specialization of submdspan_mapping [[mdspan.sub.map.left]](mdspan.sub.map.left) [🔗](#lib:layout_left::mapping,submdspan-mapping-impl) `template template constexpr auto layout_left::mapping::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below; ` [1](#mdspan.sub.map.left-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25688) *Returns*: - [(1.1)](#mdspan.sub.map.left-1.1) submdspan_mapping_result{*this, 0}, if Extents​::​rank() == 0 is true; - [(1.2)](#mdspan.sub.map.left-1.2) otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if SubExtents​::​rank() == 0 is true; - [(1.3)](#mdspan.sub.map.left-1.3) otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if * [(1.3.1)](#mdspan.sub.map.left-1.3.1) for each k in the range [0, SubExtents​::​rank() - 1)), is_convertible_v is true; and * [(1.3.2)](#mdspan.sub.map.left-1.3.2) for k equal to SubExtents​::​rank() - 1, Sk is a unit-stride slice for mapping; [*Note [1](#mdspan.sub.map.left-note-1)*: If the above conditions are true, all Sk with k larger than SubExtents​::​rank() - 1 are convertible to index_type[.](#mdspan.sub.map.left-1.3.sentence-1) — *end note*] - [(1.4)](#mdspan.sub.map.left-1.4) otherwise,submdspan_mapping_result{layout_left_padded::mapping(sub_ext, stride(u + 1)), offset} if for a value u for which u+1 is the smallest value p larger than zero for which Sp is a unit-stride slice for mapping, the following conditions are met: * [(1.4.1)](#mdspan.sub.map.left-1.4.1) S0 is a unit-stride slice for mapping; and * [(1.4.2)](#mdspan.sub.map.left-1.4.2) for each k in the range [u + 1, u + SubExtents​::​rank() - 1),is_convertible_v is true; and * [(1.4.3)](#mdspan.sub.map.left-1.4.3) for k equal to u + SubExtents​::​rank() - 1,Sk is a unit-stride slice for mapping; and where S_static is: * [(1.4.4)](#mdspan.sub.map.left-1.4.4) dynamic_extent, if static_extent(k) is dynamic_extent for any k in the range [0, u + 1), * [(1.4.5)](#mdspan.sub.map.left-1.4.5) otherwise, the product of all valuesstatic_extent(k) for k in the range [0, u + 1); - [(1.5)](#mdspan.sub.map.left-1.5) otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} #### [23.7.3.7.6.3](#mdspan.sub.map.right) layout_right specialization of submdspan_mapping [[mdspan.sub.map.right]](mdspan.sub.map.right) [🔗](#lib:layout_right::mapping,submdspan-mapping-impl) `template template constexpr auto layout_right::mapping::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below; ` [1](#mdspan.sub.map.right-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25764) *Returns*: - [(1.1)](#mdspan.sub.map.right-1.1) submdspan_mapping_result{*this, 0}, if Extents​::​rank() == 0 is true; - [(1.2)](#mdspan.sub.map.right-1.2) otherwise,submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset}, if SubExtents​::​rank() == 0 is true; - [(1.3)](#mdspan.sub.map.right-1.3) otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if * [(1.3.1)](#mdspan.sub.map.right-1.3.1) for each k in the range [*rank_* - SubExtents​::​rank() + 1, *rank_*), is_convertible_v is true; and * [(1.3.2)](#mdspan.sub.map.right-1.3.2) for k equal to *_rank* - SubExtents​::​rank(), Sk is a unit-stride slice for mapping; [*Note [1](#mdspan.sub.map.right-note-1)*: If the above conditions are true, all Sk with k<_rank - SubExtents::rank() are convertible to index_type[.](#mdspan.sub.map.right-1.3.sentence-1) — *end note*] - [(1.4)](#mdspan.sub.map.right-1.4) otherwise,submdspan_mapping_result{layout_right_padded::mapping(sub_ext, stride(*rank_* - u - 2)), offset} if for a value u for which rank_−u−2 is the largest value p smaller than *rank_* - 1 for which Sp is a unit-stride slice for mapping, the following conditions are met: * [(1.4.1)](#mdspan.sub.map.right-1.4.1) for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping; and * [(1.4.2)](#mdspan.sub.map.right-1.4.2) for each k in the range [*rank_* - SubExtents​::​rank() - u + 1, *rank_* - u - 1),is_convertible_v is true; and * [(1.4.3)](#mdspan.sub.map.right-1.4.3) for k equal to *rank_* - SubExtents​::​rank() - u, Sk is a unit-stride slice for mapping; and where S_static is: * [(1.4.4)](#mdspan.sub.map.right-1.4.4) dynamic_extent, if static_extent(k) is dynamic_extent for any k in the range [*rank_* - u - 1, *rank_*), * [(1.4.5)](#mdspan.sub.map.right-1.4.5) otherwise, the product of all valuesstatic_extent(k) for k in the range [*rank_* - u - 1, *rank_*); - [(1.5)](#mdspan.sub.map.right-1.5) otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} #### [23.7.3.7.6.4](#mdspan.sub.map.stride) layout_stride specialization of submdspan_mapping [[mdspan.sub.map.stride]](mdspan.sub.map.stride) [🔗](#lib:layout_stride::mapping,submdspan-mapping-impl) `template template constexpr auto layout_stride::mapping::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below; ` [1](#mdspan.sub.map.stride-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25843) *Returns*: - [(1.1)](#mdspan.sub.map.stride-1.1) submdspan_mapping_result{*this, 0}, if Extents​::​rank() == 0 is true; - [(1.2)](#mdspan.sub.map.stride-1.2) otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} #### [23.7.3.7.6.5](#mdspan.sub.map.leftpad) layout_left_padded specialization of submdspan_mapping [[mdspan.sub.map.leftpad]](mdspan.sub.map.leftpad) [🔗](#lib:layout_left_padded::mapping,submdspan-mapping-impl) `template template constexpr auto layout_left_padded::mapping::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below; ` [1](#mdspan.sub.map.leftpad-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25868) *Returns*: - [(1.1)](#mdspan.sub.map.leftpad-1.1) submdspan_mapping_result{*this, 0}, if Extents​::​rank() == 0 is true; - [(1.2)](#mdspan.sub.map.leftpad-1.2) otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if *rank_* == 1 is true orSubExtents​::​rank() == 0 is true; - [(1.3)](#mdspan.sub.map.leftpad-1.3) otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if * [(1.3.1)](#mdspan.sub.map.leftpad-1.3.1) SubExtents​::​rank() == 1 is true and * [(1.3.2)](#mdspan.sub.map.leftpad-1.3.2) S0 is a unit-stride slice for mapping; - [(1.4)](#mdspan.sub.map.leftpad-1.4) otherwise,submdspan_mapping_result{layout_left_padded::mapping(sub_ext, stride(u + 1)), offset} if for a value u for which u + 1 is the smallest value p larger than zero for which Sp is a unit-stride slice for mapping, the following conditions are met: * [(1.4.1)](#mdspan.sub.map.leftpad-1.4.1) S0 is a unit-stride slice for mapping; and * [(1.4.2)](#mdspan.sub.map.leftpad-1.4.2) for each k in the range [u + 1, u + SubExtents​::​rank() - 1),is_convertible_v is true; and * [(1.4.3)](#mdspan.sub.map.leftpad-1.4.3) for k equal to u + SubExtents​::​rank() - 1,Sk is a unit-stride slice for mapping; where S_static is: * [(1.4.4)](#mdspan.sub.map.leftpad-1.4.4) dynamic_extent, if *static-padding-stride* is dynamic_extent orstatic_extent(k) is dynamic_extent for any k in the range [1, u + 1), * [(1.4.5)](#mdspan.sub.map.leftpad-1.4.5) otherwise, the product of *static-padding-stride* and all values static_extent(k) for k in the range [1, u + 1); - [(1.5)](#mdspan.sub.map.leftpad-1.5) otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} #### [23.7.3.7.6.6](#mdspan.sub.map.rightpad) layout_right_padded specialization of submdspan_mapping [[mdspan.sub.map.rightpad]](mdspan.sub.map.rightpad) [🔗](#lib:layout_right_padded::mapping,submdspan-mapping-impl) `template template constexpr auto layout_right_padded::mapping::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below; ` [1](#mdspan.sub.map.rightpad-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25939) *Returns*: - [(1.1)](#mdspan.sub.map.rightpad-1.1) submdspan_mapping_result{*this, 0}, if *rank_* == 0 is true; - [(1.2)](#mdspan.sub.map.rightpad-1.2) otherwise,submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset}, if *rank_* == 1 is true orSubExtents​::​rank() == 0 is true; - [(1.3)](#mdspan.sub.map.rightpad-1.3) otherwise,submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset}, if * [(1.3.1)](#mdspan.sub.map.rightpad-1.3.1) SubExtents​::​rank() == 1 is true and * [(1.3.2)](#mdspan.sub.map.rightpad-1.3.2) for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping; - [(1.4)](#mdspan.sub.map.rightpad-1.4) otherwise,submdspan_mapping_result{layout_right_padded::mapping(sub_ext, stride(*rank_* - u - 2)), offset} if for a value u for which *rank_* - u - 2 is the largest value p smaller than *rank_* - 1 for which Sp is a unit-stride slice for mapping, the following conditions are met: * [(1.4.1)](#mdspan.sub.map.rightpad-1.4.1) for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping; and * [(1.4.2)](#mdspan.sub.map.rightpad-1.4.2) for each k in the range [*rank_* - SubExtents​::​rank() - u + 1, *rank_* - u - 1)),is_convertible_v is true; and * [(1.4.3)](#mdspan.sub.map.rightpad-1.4.3) for k equal to *rank_* - SubExtents​::​rank() - u, Sk is a unit-stride slice for mapping; and where S_static is: * [(1.4.4)](#mdspan.sub.map.rightpad-1.4.4) dynamic_extent if *static-padding-stride* is dynamic_extent or for any k in the range [*rank_* - u - 1, *rank_* - 1)static_extent(k) is dynamic_extent, * [(1.4.5)](#mdspan.sub.map.rightpad-1.4.5) otherwise, the product of *static-padding-stride* and all values static_extent(k) with k in the range [*rank_* - u - 1, *rank_* - 1); - [(1.5)](#mdspan.sub.map.rightpad-1.5) otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} #### [23.7.3.7.7](#mdspan.sub.sub) submdspan function template [[mdspan.sub.sub]](mdspan.sub.sub) [🔗](#lib:submdspan) `template constexpr auto submdspan( const mdspan& src, SliceSpecifiers... slices) -> see below; ` [1](#mdspan.sub.sub-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26016) Let index_type be typename Extents​::​index_type[.](#mdspan.sub.sub-1.sentence-1) [2](#mdspan.sub.sub-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26019) Let sub_map_offset be the result ofsubmdspan_mapping(src.mapping(), slices...)[.](#mdspan.sub.sub-2.sentence-1) [*Note [1](#mdspan.sub.sub-note-1)*: This invocation of submdspan_mapping selects a function call via overload resolution on a candidate set that includes the lookup set found by argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup"))[.](#mdspan.sub.sub-2.sentence-2) — *end note*] [3](#mdspan.sub.sub-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26029) *Constraints*: - [(3.1)](#mdspan.sub.sub-3.1) sizeof...(slices) equals Extents​::​rank(), and - [(3.2)](#mdspan.sub.sub-3.2) the expression submdspan_mapping(src.mapping(), slices...) is well-formed when treated as an unevaluated operand[.](#mdspan.sub.sub-3.sentence-1) [4](#mdspan.sub.sub-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26039) *Mandates*: - [(4.1)](#mdspan.sub.sub-4.1) decltype(submdspan_mapping(src.mapping(), slices...)) is a specialization of submdspan_mapping_result[.](#mdspan.sub.sub-4.1.sentence-1) - [(4.2)](#mdspan.sub.sub-4.2) is_same_v,decltype(submdspan_extents(src.mapping(), slices...))> is true[.](#mdspan.sub.sub-4.2.sentence-1) - [(4.3)](#mdspan.sub.sub-4.3) For each rank index k of src.extents(), exactly one of the following is true: * [(4.3.1)](#mdspan.sub.sub-4.3.1) Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), * [(4.3.2)](#mdspan.sub.sub-4.3.2) Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2 Header synopsis [mdspan.syn]"), * [(4.3.3)](#mdspan.sub.sub-4.3.3) is_convertible_v is true, or * [(4.3.4)](#mdspan.sub.sub-4.3.4) Sk is a specialization of strided_slice[.](#mdspan.sub.sub-4.3.sentence-1) [5](#mdspan.sub.sub-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26062) *Preconditions*: - [(5.1)](#mdspan.sub.sub-5.1) For each rank index k of src.extents(), all of the following are true: * [(5.1.1)](#mdspan.sub.sub-5.1.1) if Sk is a specialization of strided_slice + [(5.1.1.1)](#mdspan.sub.sub-5.1.1.1) sk.extent=0, or + [(5.1.1.2)](#mdspan.sub.sub-5.1.1.2) sk.stride>0 * [(5.1.2)](#mdspan.sub.sub-5.1.2) 0 ≤ *first_*(slices...) ≤ *last_*(src.extents(), slices...) ≤ src.extent(k) - [(5.2)](#mdspan.sub.sub-5.2) sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...) is true; and - [(5.3)](#mdspan.sub.sub-5.3) for each integer pack I which is a multidimensional index in sub_map_offset.mapping.extents(),sub_map_offset.mapping(I...) + sub_map_offset.offset == src.mapping()(*src-indices*(array{I...}, slices...)) is true[.](#mdspan.sub.sub-5.sentence-1) [*Note [2](#mdspan.sub.sub-note-2)*: These conditions ensure that the mapping returned by submdspan_mapping matches the algorithmically expected index-mapping given the slice specifiers[.](#mdspan.sub.sub-5.sentence-2) — *end note*] [6](#mdspan.sub.sub-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26100) *Effects*: Equivalent to:auto sub_map_result = submdspan_mapping(src.mapping(), slices...);return mdspan(src.accessor().offset(src.data_handle(), sub_map_result.offset), sub_map_result.mapping, typename AccessorPolicy::offset_policy(src.accessor())); [7](#mdspan.sub.sub-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26111) [*Example [1](#mdspan.sub.sub-example-1)*: Given a rank-3 mdspan grid3d representing a three-dimensional grid of regularly spaced points in a rectangular prism, the function zero_surface sets all elements on the surface of the 3-dimensional shape to zero[.](#mdspan.sub.sub-7.sentence-1) It does so by reusing a function zero_2d that takes a rank-2 mdspan[.](#mdspan.sub.sub-7.sentence-2) // zero out all elements in an mdspantemplatevoid zero_2d(mdspan a) {static_assert(a.rank() == 2); for (int i = 0; i < a.extent(0); i++)for (int j = 0; j < a.extent(1); j++) a[i, j] = 0;}// zero out just the surfacetemplatevoid zero_surface(mdspan grid3d) {static_assert(grid3d.rank() == 3); zero_2d(submdspan(grid3d, 0, full_extent, full_extent)); zero_2d(submdspan(grid3d, full_extent, 0, full_extent)); zero_2d(submdspan(grid3d, full_extent, full_extent, 0)); zero_2d(submdspan(grid3d, grid3d.extent(0) - 1, full_extent, full_extent)); zero_2d(submdspan(grid3d, full_extent, grid3d.extent(1) - 1, full_extent)); zero_2d(submdspan(grid3d, full_extent, full_extent, grid3d.extent(2) - 1));} — *end example*]