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

5223 lines
214 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

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

[views.multidim]
# 23 Containers library [[containers]](./#containers)
## 23.7 Views [[views]](views#multidim)
### 23.7.3 Multidimensional access [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.1Overview[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.1Overview[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.1Overview[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.1Overview[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.1Overview[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 <mdspan> synopsis [[mdspan.syn]](mdspan.syn)
[🔗](#header:%3cmdspan%3e)
// mostly freestandingnamespace std {// [[mdspan.extents]](#mdspan.extents "23.7.3.3Class template extents"), class template extentstemplate<class IndexType, size_t... Extents>class extents; // [[mdspan.extents.dextents]](#mdspan.extents.dextents "23.7.3.3.6Alias template dextents"), alias template dextentstemplate<class IndexType, size_t Rank>using dextents = *see below*; // [[mdspan.extents.dims]](#mdspan.extents.dims "23.7.3.3.7Alias template dims"), alias template dimstemplate<size_t Rank, class IndexType = size_t>using dims = *see below*; // [[mdspan.layout]](#mdspan.layout "23.7.3.4Layout mapping"), layout mappingstruct layout_left; struct layout_right; struct layout_stride; template<size_t PaddingValue = dynamic_extent>struct layout_left_padded; template<size_t PaddingValue = dynamic_extent>struct layout_right_padded; // [[mdspan.accessor.default]](#mdspan.accessor.default "23.7.3.5.3Class template default_­accessor"), class template default_accessortemplate<class ElementType>class default_accessor; // [[mdspan.accessor.aligned]](#mdspan.accessor.aligned "23.7.3.5.4Class template aligned_­accessor"), class template aligned_accessortemplate<class ElementType, size_t ByteAlignment>class aligned_accessor; // [[mdspan.mdspan]](#mdspan.mdspan "23.7.3.6Class template mdspan"), class template mdspantemplate<class ElementType, class Extents, class LayoutPolicy = layout_right, class AccessorPolicy = default_accessor<ElementType>>class mdspan; // partially freestanding// [[mdspan.sub]](#mdspan.sub "23.7.3.7submdspan"), submdspan creationtemplate<class OffsetType, class LengthType, class StrideType>struct strided_slice; template<class LayoutMapping>struct submdspan_mapping_result; struct full_extent_t { explicit full_extent_t() = default; }; inline constexpr full_extent_t full_extent{}; template<class IndexType, size_t... Extents, class... SliceSpecifiers>constexpr auto submdspan_extents(const extents<IndexType, Extents...>&, SliceSpecifiers...); // [[mdspan.sub.sub]](#mdspan.sub.sub "23.7.3.7.7submdspan function template"), submdspan function templatetemplate<class ElementType, class Extents, class LayoutPolicy, class AccessorPolicy, class... SliceSpecifiers>constexpr auto submdspan(const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
SliceSpecifiers... slices) -> *see below*; template<class T, class IndexType>concept [*index-pair-like*](#concept:index-pair-like "23.7.3.2Header <mdspan> synopsis[mdspan.syn]") = // *exposition only*[*pair-like*](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]")<T> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<tuple_element_t<0, T>, IndexType> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<tuple_element_t<1, T>, 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]](views "23.7Views"),extents is used synonymously with multidimensional index space[.](#mdspan.extents.overview-sentence-2)
namespace std {template<class IndexType, size_t... Extents>class [extents](#lib:extents "23.7.3.3.1Overview[mdspan.extents.overview]") {public:using index_type = IndexType; using size_type = make_unsigned_t<index_type>; using rank_type = size_t; // [[mdspan.extents.obs]](#mdspan.extents.obs "23.7.3.3.4Observers 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.3Constructors"), constructorsconstexpr extents() noexcept = default; template<class OtherIndexType, size_t... OtherExtents>constexpr explicit(*see below*) extents(const extents<OtherIndexType, OtherExtents...>&) noexcept; template<class... OtherIndexTypes>constexpr explicit extents(OtherIndexTypes...) noexcept; template<class OtherIndexType, size_t N>constexpr explicit(N != rank_dynamic()) extents(span<OtherIndexType, N>) noexcept; template<class OtherIndexType, size_t N>constexpr explicit(N != rank_dynamic()) extents(const array<OtherIndexType, N>&) noexcept; // [[mdspan.extents.cmp]](#mdspan.extents.cmp "23.7.3.3.5Comparison operators"), comparison operatorstemplate<class OtherIndexType, size_t... OtherExtents>friend constexpr bool operator==(const extents&, const extents<OtherIndexType, OtherExtents...>&) noexcept; // [[mdspan.extents.expo]](#mdspan.extents.expo "23.7.3.3.2Exposition-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*template<class OtherIndexType>static 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<index_type, rank_dynamic()> *dynamic-extents*{}; // *exposition only*}; template<class... Integrals>explicit 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.6Object 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.1Overview[mdspan.extents.overview]") if it is equal to dynamic_extent,
otherwise Er is a [*static extent*](#def:extent,static "23.7.3.3.1Overview[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<i for which Er is a dynamic extent[.](#mdspan.extents.expo-2.sentence-1)
[🔗](#mdspan.extents.expo-itemdecl:2)
`static constexpr rank_type dynamic-index-inv(rank_type i) noexcept;
`
[3](#mdspan.extents.expo-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21199)
*Preconditions*: i < rank_dynamic() is true[.](#mdspan.extents.expo-3.sentence-1)
[4](#mdspan.extents.expo-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21203)
*Returns*: The minimum value of r such that *dynamic-index*(r + 1) == i + 1 is true[.](#mdspan.extents.expo-4.sentence-1)
[🔗](#mdspan.extents.expo-itemdecl:3)
`constexpr size_t fwd-prod-of-extents(rank_type i) const noexcept;
`
[5](#mdspan.extents.expo-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21214)
*Preconditions*: i <= rank() is true[.](#mdspan.extents.expo-5.sentence-1)
[6](#mdspan.extents.expo-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21218)
*Returns*: If i > 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<class OtherIndexType>
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<index_type>(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<class OtherIndexType, size_t... OtherExtents>
constexpr explicit(see below)
extents(const extents<OtherIndexType, OtherExtents...>& 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<index_type>::max() < numeric_limits<OtherIndexType>::max())
[🔗](#lib:extents,constructor_)
`template<class... OtherIndexTypes>
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<index_type, N>{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<OtherIndexTypes, index_type> && ...) is true,
- [(6.2)](#mdspan.extents.cons-6.2)
(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) 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<class OtherIndexType, size_t N>
constexpr explicit(N != rank_dynamic())
extents(span<OtherIndexType, N> exts) noexcept;
template<class OtherIndexType, size_t N>
constexpr explicit(N != rank_dynamic())
extents(const array<OtherIndexType, N>& 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<const OtherIndexType&, index_type> is true,
- [(9.2)](#mdspan.extents.cons-9.2)
is_nothrow_constructible_v<index_type, const OtherIndexType&> 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<class... Integrals>
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<Integrals, size_t> && ...) 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<size_t, [*maybe-static-ext*](span.syn#concept:maybe-static-ext "23.7.2.1Header <span> synopsis[span.syn]")<Integrals>...>[.](#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<class OtherIndexType, size_t... OtherExtents>
friend constexpr bool operator==(const extents& lhs,
const extents<OtherIndexType, OtherExtents...>& 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<class IndexType, size_t Rank>
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<size_t Rank, class IndexType = size_t>
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.2Requirements") and [[mdspan.layout.policy.reqmts]](#mdspan.layout.policy.reqmts "23.7.3.4.3Layout 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.1Overview"))[.](#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.2Requirements") through [[mdspan.layout.stride]](#mdspan.layout.stride "23.7.3.4.7Class template layout_­stride::mapping"):
- [(2.1)](#mdspan.layout.general-2.1)
Let *is-mapping-of* be the exposition-only variable template defined as follows:template<class Layout, class Mapping>constexpr bool *is-mapping-of* = // *exposition only* is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
- [(2.2)](#mdspan.layout.general-2.2)
Let *is-layout-left-padded-mapping-of* be
the exposition-only variable template defined as follows:template<class Mapping>constexpr bool *is-layout-left-padded-mapping-of* = *see below*; // *exposition only* where *is-layout-left-padded-mapping-of*<Mapping> is true if and only if Mapping denotes
a specialization of layout_left_padded<S>::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:template<class Mapping>constexpr bool *is-layout-right-padded-mapping-of* = *see below*; // *exposition only* where *is-layout-right-padded-mapping-of*<Mapping> is true if and only if Mapping denotes
a specialization of layout_right_padded<S>::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.2Requirements[mdspan.layout.reqmts]") requirements if
- [(1.1)](#mdspan.layout.reqmts-1.1)
M models [copyable](concepts.object#concept:copyable "18.6Object concepts[concepts.object]") and [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4Concept equality_­comparable[concept.equalitycomparable]"),
- [(1.2)](#mdspan.layout.reqmts-1.2)
is_nothrow_move_constructible_v<M> is true,
- [(1.3)](#mdspan.layout.reqmts-1.3)
is_nothrow_move_assignable_v<M> is true,
- [(1.4)](#mdspan.layout.reqmts-1.4)
is_nothrow_swappable_v<M> 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.3Layout mapping policy requirements")) and
for which *is-mapping-of*<MP, M> 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<typename M::index_type>::max() and
less than or equal to numeric_limits<size_t>::max()[.](#mdspan.layout.reqmts-8.sentence-1)
[🔗](#mdspan.layout.reqmts-itemdecl:7)
`m(i...) == m(static_cast<typename M::index_type>(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.1Overview")),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.7Constant 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.7Constant 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.7Constant 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.3Layout mapping policy requirements[mdspan.layout.policy.reqmts]") requirements
if for a type E that is a specialization of extents,MP::mapping<E> is valid and denotes a type X that meets the layout mapping requirements ([[mdspan.layout.reqmts]](#mdspan.layout.reqmts "23.7.3.4.2Requirements")), and
for which the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified 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.3Qualified 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 {template<class Extents>class mapping; }; struct layout_right {template<class Extents>class mapping; }; struct layout_stride {template<class Extents>class mapping; }; template<size_t PaddingValue>struct layout_left_padded {template<class Extents> class mapping; }; template<size_t PaddingValue>struct layout_right_padded {template<class Extents> 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<T> 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 {template<class Extents>class 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.2Constructors"), constructorsconstexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; template<class OtherExtents>constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>&) noexcept; template<class OtherExtents>constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>&) noexcept; template<class LayoutLeftPaddedMapping>constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
extents_type>) mapping(const LayoutLeftPaddedMapping&) noexcept; template<class OtherExtents>constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<OtherExtents>&); constexpr mapping& operator=(const mapping&) noexcept = default; // [[mdspan.layout.left.obs]](#mdspan.layout.left.obs "23.7.3.4.5.3Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const noexcept; template<class... Indices>constexpr 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; template<class OtherExtents>friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept; private: extents_type *extents_*{}; // *exposition only*// [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6Specializations of submdspan_­mapping"), submdspan mapping specializationtemplate<class... SliceSpecifiers>constexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; template<class... SliceSpecifiers>friend 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<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6Object 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.2Fundamental 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<class OtherExtents>
constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
mapping(const mapping<OtherExtents>& other) noexcept;
`
[3](#mdspan.layout.left.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22030)
*Constraints*: is_constructible_v<extents_type, OtherExtents> 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.2Fundamental 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<class OtherExtents>
constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
mapping(const layout_right::mapping<OtherExtents>& 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<extents_type, OtherExtents> 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.2Fundamental 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<class LayoutLeftPaddedMapping>
constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
extents_type>)
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*<LayoutLeftPaddedMapping> is true[.](#mdspan.layout.left.cons-9.1.sentence-1)
- [(9.2)](#mdspan.layout.left.cons-9.2)
is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>
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<class OtherExtents>
constexpr explicit(extents_type::rank() > 0)
mapping(const layout_stride::mapping<OtherExtents>& other);
`
[13](#mdspan.layout.left.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22128)
*Constraints*: is_constructible_v<extents_type, OtherExtents> 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.2Fundamental 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<class... Indices>
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<Indices, index_type> && ...) is true, and
- [(2.3)](#mdspan.layout.left.obs-2.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) 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.1Overview"))[.](#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_for<Indices...>, index_sequence<P...>> is true[.](#mdspan.layout.left.obs-4.sentence-1)
Equivalent to:return ((static_cast<index_type>(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<class OtherExtents>
friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& 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 {template<class Extents>class 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.2Constructors"), constructorsconstexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; template<class OtherExtents>constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>&) noexcept; template<class OtherExtents>constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>&) noexcept; template<class LayoutRightPaddedMapping>constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
extents_type>) mapping(const LayoutRightPaddedMapping&) noexcept; template<class OtherExtents>constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<OtherExtents>&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [[mdspan.layout.right.obs]](#mdspan.layout.right.obs "23.7.3.4.6.3Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const noexcept; template<class... Indices>constexpr 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; template<class OtherExtents>friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept; private: extents_type *extents_*{}; // *exposition only*// [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6Specializations of submdspan_­mapping"), submdspan mapping specializationtemplate<class... SliceSpecifiers>constexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; template<class... SliceSpecifiers>friend 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<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6Object 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.2Fundamental 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<class OtherExtents>
constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
mapping(const mapping<OtherExtents>& other) noexcept;
`
[3](#mdspan.layout.right.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22352)
*Constraints*: is_constructible_v<extents_type, OtherExtents> 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.2Fundamental 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<class OtherExtents>
constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
mapping(const layout_left::mapping<OtherExtents>& 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<extents_type, OtherExtents> 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.2Fundamental 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<class LayoutRightPaddedMapping>
constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
extents_type>)
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*<LayoutRightPaddedMapping> is true[.](#mdspan.layout.right.cons-9.1.sentence-1)
- [(9.2)](#mdspan.layout.right.cons-9.2)
is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type> 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<class OtherExtents>
constexpr explicit(extents_type::rank() > 0)
mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
`
[13](#mdspan.layout.right.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22454)
*Constraints*: is_constructible_v<extents_type, OtherExtents> 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.2Fundamental 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<class... Indices>
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<Indices, index_type> && ...) is true, and
- [(2.3)](#mdspan.layout.right.obs-2.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) 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.1Overview"))[.](#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_for<Indices...>, index_sequence<P...>> is true[.](#mdspan.layout.right.obs-4.sentence-1)
Equivalent to:return ((static_cast<index_type>(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<class OtherExtents>
friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& 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 {template<class Extents>class 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.3Constructors"), constructorsconstexpr mapping() noexcept; constexpr mapping(const mapping&) noexcept = default; template<class OtherIndexType>constexpr mapping(const extents_type&, span<OtherIndexType, *rank_*>) noexcept; template<class OtherIndexType>constexpr mapping(const extents_type&, const array<OtherIndexType, *rank_*>&) noexcept; template<class StridedLayoutMapping>constexpr 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.4Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr array<index_type, *rank_*> strides() const noexcept { return *strides_*; }constexpr index_type required_span_size() const noexcept; template<class... Indices>constexpr 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]; }template<class OtherMapping>friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept; private: extents_type *extents_*{}; // *exposition only* array<index_type, *rank_*> *strides_*{}; // *exposition only*// [[mdspan.sub.map]](#mdspan.sub.map "23.7.3.7.6Specializations of submdspan_­mapping"), submdspan mapping specializationtemplate<class... SliceSpecifiers>constexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; template<class... SliceSpecifiers>friend 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<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6Object 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:template<class T>constexpr bool *is-extents* = false; // *exposition only*template<class IndexType, size_t... Args>constexpr bool *is-extents*<extents<IndexType, Args...>> = 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.2Exposition-only helpers[mdspan.layout.stride.expo]") be the exposition-only concept
defined as follows:template<class M>concept [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2Exposition-only helpers[mdspan.layout.stride.expo]") = requires { // *exposition only*requires *is-extents*<typename M::extents_type>; { M::is_always_strided() } -> [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<bool>; { M::is_always_exhaustive() } -> [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<bool>; { M::is_always_unique() } -> [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<bool>;
bool_constant<M::is_always_strided()>::value;
bool_constant<M::is_always_exhaustive()>::value;
bool_constant<M::is_always_unique()>::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<extents_type>().required_span_size() is representable as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental 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<extents_type>().stride(d)[.](#mdspan.layout.stride.cons-2.sentence-1)
[🔗](#lib:layout_stride::mapping,constructor_)
`template<class OtherIndexType>
constexpr mapping(const extents_type& e, span<OtherIndexType, rank_> s) noexcept;
template<class OtherIndexType>
constexpr mapping(const extents_type& e, const array<OtherIndexType, rank_>& 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<const OtherIndexType&, index_type> is true, and
- [(3.2)](#mdspan.layout.stride.cons-3.2)
is_nothrow_constructible_v<index_type, const OtherIndexType&> 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.2Fundamental 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<class StridedLayoutMapping>
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.2Exposition-only helpers[mdspan.layout.stride.expo]")<StridedLayoutMapping> is satisfied[.](#mdspan.layout.stride.cons-6.1.sentence-1)
- [(6.2)](#mdspan.layout.stride.cons-6.2)
is_constructible_v<extents_type, typename StridedLayoutMapping::extents_type> 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.2Requirements")),
- [(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.2Fundamental 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<typename StridedLayoutMapping::extents_type, extents_type> &&(*is-mapping-of*<layout_left, StridedLayoutMapping> ||*is-mapping-of*<layout_right, StridedLayoutMapping> ||*is-layout-left-padded-mapping-of*<StridedLayoutMapping> ||*is-layout-right-padded-mapping-of*<StridedLayoutMapping> ||*is-mapping-of*<layout_stride, StridedLayoutMapping>))
#### [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<class... Indices>
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<Indices, index_type> && ...) is true, and
- [(2.3)](#mdspan.layout.stride.obs-2.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) 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.1Overview"))[.](#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_for<Indices...>, index_sequence<P...>> is true[.](#mdspan.layout.stride.obs-4.sentence-1)
Equivalent to:return ((static_cast<index_type>(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<class OtherMapping>
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.2Exposition-only helpers[mdspan.layout.stride.expo]")<OtherMapping> 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.3Layout 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 {template<size_t PaddingValue>template<class Extents>class layout_left_padded<PaddingValue>::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<PaddingValue>; 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.2Exposition-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.3Constructors"), constructorsconstexpr mapping() noexcept : mapping(extents_type{}) {}constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&); template<class OtherIndexType>constexpr mapping(const extents_type&, OtherIndexType); template<class OtherExtents>constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>&); template<class OtherExtents>constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<OtherExtents>&); template<class LayoutLeftPaddedMapping>constexpr explicit(*see below*) mapping(const LayoutLeftPaddedMapping&); template<class LayoutRightPaddedMapping>constexpr 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.4Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr array<index_type, rank_> strides() const noexcept; constexpr index_type required_span_size() const noexcept; template<class... Indices>constexpr 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; template<class LayoutLeftPaddedMapping>friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept; private:// [[mdspan.layout.leftpad.expo]](#mdspan.layout.leftpad.expo "23.7.3.4.8.2Exposition-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.6Specializations of submdspan_­mapping"), submdspan mapping specializationtemplate<class... SliceSpecifiers>constexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; template<class... SliceSpecifiers>friend 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<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6Object 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.8Class 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<index_type, *static-padding-stride*> 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<class OtherIndexType>
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<OtherIndexType, index_type> is true[.](#mdspan.layout.leftpad.cons-3.1.sentence-1)
- [(3.2)](#mdspan.layout.leftpad.cons-3.2)
is_nothrow_constructible_v<index_type, OtherIndexType> 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<class OtherExtents>
constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
mapping(const layout_left::mapping<OtherExtents>& other);
`
[6](#mdspan.layout.leftpad.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23236)
*Constraints*: is_constructible_v<extents_type, OtherExtents> 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<class OtherExtents>
constexpr explicit(rank_ > 0)
mapping(const layout_stride::mapping<OtherExtents>& other);
`
[10](#mdspan.layout.leftpad.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23280)
*Constraints*: is_constructible_v<extents_type, OtherExtents> 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<class LayoutLeftPaddedMapping>
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*<LayoutLeftPaddedMapping> is true[.](#mdspan.layout.leftpad.cons-13.1.sentence-1)
- [(13.2)](#mdspan.layout.leftpad.cons-13.2)
is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>
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<class LayoutRightPaddedMapping>
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*<LayoutRightPaddedMapping> is true or
*is-mapping-of*<layout_right, LayoutRightPaddedMapping> 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<extents_type, typename LayoutRightPaddedMapping::extents_-
type> 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<typename LayoutRightPaddedMapping::extents_type, extents_type>
[*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<index_type, rank_> strides() const noexcept;
`
[1](#mdspan.layout.leftpad.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23442)
*Returns*: array<index_type, *rank_*>({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<class... Indices>
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<Indices, index_type> && ...) is true[.](#mdspan.layout.leftpad.obs-3.2.sentence-1)
- [(3.3)](#mdspan.layout.leftpad.obs-3.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) 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.1Overview"))[.](#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<index_type>(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<class LayoutLeftPaddedMapping>
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*<LayoutLeftPaddedMapping> 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 {template<size_t PaddingValue>template<class Extents>class layout_right_padded<PaddingValue>::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<PaddingValue>; 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.2Exposition-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.3Constructors"), constructorsconstexpr mapping() noexcept : mapping(extents_type{}) {}constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&); template<class OtherIndexType>constexpr mapping(const extents_type&, OtherIndexType); template<class OtherExtents>constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>&); template<class OtherExtents>constexpr explicit(rank_ > 0) mapping(const layout_stride::mapping<OtherExtents>&); template<class LayoutRightPaddedMapping>constexpr explicit(*see below*) mapping(const LayoutRightPaddedMapping&); template<class LayoutLeftPaddedMapping>constexpr 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.4Observers"), observersconstexpr const extents_type& extents() const noexcept { return extents_; }constexpr array<index_type, rank_> strides() const noexcept; constexpr index_type required_span_size() const noexcept; template<class... Indices>constexpr 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; template<class LayoutRightPaddedMapping>friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept; private:// [[mdspan.layout.rightpad.expo]](#mdspan.layout.rightpad.expo "23.7.3.4.9.2Exposition-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.6Specializations of submdspan_­mapping"), submdspan mapping specializationtemplate<class... SliceSpecifiers>constexpr auto *submdspan-mapping-impl*(SliceSpecifiers...) const // *exposition only*-> *see below*; template<class... SliceSpecifiers>friend 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<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6Object 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.9Class 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<index_type, *static-padding-stride*> 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<class OtherIndexType>
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<OtherIndexType, index_type> is true[.](#mdspan.layout.rightpad.cons-3.1.sentence-1)
- [(3.2)](#mdspan.layout.rightpad.cons-3.2)
is_nothrow_constructible_v<index_type, OtherIndexType> 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<class OtherExtents>
constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
mapping(const layout_right::mapping<OtherExtents>& other);
`
[6](#mdspan.layout.rightpad.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23864)
*Constraints*: is_constructible_v<extents_type, OtherExtents> 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<class OtherExtents>
constexpr explicit(rank_ > 0)
mapping(const layout_stride::mapping<OtherExtents>& other);
`
[10](#mdspan.layout.rightpad.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23908)
*Constraints*: is_constructible_v<extents_type, OtherExtents> 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<class LayoutRightPaddedMapping>
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*<LayoutRightPaddedMapping> is true[.](#mdspan.layout.rightpad.cons-13.1.sentence-1)
- [(13.2)](#mdspan.layout.rightpad.cons-13.2)
is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type> 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<class LayoutLeftPaddedMapping>
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*<LayoutLeftPaddedMapping> is true or
*is-mapping-of*<layout_left, LayoutLeftPaddedMapping> 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<extents_type, typename LayoutLeftPaddedMapping::extents_type>
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<typename LayoutLeftPaddedMapping::extents_type, extents_type>
[*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<index_type, rank_> strides() const noexcept;
`
[1](#mdspan.layout.rightpad.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24070)
*Returns*: array<index_type, *rank_*>(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<class... Indices>
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<Indices, index_type> && ...) is true[.](#mdspan.layout.rightpad.obs-3.2.sentence-1)
- [(3.3)](#mdspan.layout.rightpad.obs-3.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) 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.1Overview"))[.](#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<index_type>(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<class LayoutRightPaddedMapping>
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*<LayoutRightPaddedMapping> 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.1General[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.1General[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.2Requirements"),
- [(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.6Object concepts[concepts.object]"),
- [(1.2)](#mdspan.accessor.reqmts-1.2)
is_nothrow_move_constructible_v<A> is true,
- [(1.3)](#mdspan.accessor.reqmts-1.3)
is_nothrow_move_assignable_v<A> is true,
- [(1.4)](#mdspan.accessor.reqmts-1.4)
is_nothrow_swappable_v<A> 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.6Object concepts[concepts.object]"), and
for which is_nothrow_move_constructible_v<A::data_handle_type> is true,is_nothrow_move_assignable_v<A::data_handle_type> is true, andis_nothrow_swappable_v<A::data_handle_type> 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.5Concept common_­reference_­with[concept.commonref]")<A::reference&&, A::element_type&>[.](#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.11Concept constructible_­from[concept.constructible]")<OP, const A&> is modeled, and
- [(5.3)](#mdspan.accessor.reqmts-5.3)
is_same_v<typename OP::element_type, typename A::element_type> 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<A::element_type, dynamic_extent> 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 {template<class ElementType>struct default_accessor {using offset_policy = default_accessor; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; constexpr default_accessor() noexcept = default; template<class OtherElementType>constexpr default_accessor(default_accessor<OtherElementType>) 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.6Object 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<class OtherElementType>
constexpr default_accessor(default_accessor<OtherElementType>) noexcept {}
`
[1](#mdspan.accessor.default.members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24408)
*Constraints*: is_convertible_v<OtherElementType(*)[], element_type(*)[]> 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 {template<class ElementType, size_t ByteAlignment>struct [aligned_accessor](#lib:aligned_accessor "23.7.3.5.4.1Overview[mdspan.accessor.aligned.overview]") {using offset_policy = default_accessor<ElementType>; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; static constexpr size_t byte_alignment = ByteAlignment; constexpr aligned_accessor() noexcept = default; template<class OtherElementType, size_t OtherByteAlignment>constexpr aligned_accessor( aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept; template<class OtherElementType>constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept; template<class OtherElementType>constexpr operator default_accessor<OtherElementType>() 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.6Object 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<byte_alignment>(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<float, 4 * sizeof(float)>[.](#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<float, std::dims<1>, std::layout_right,
std::aligned_accessor<float, 4 * alignof(float)>> x);
void compute_without_requiring_overalignment( std::mdspan<float, std::dims<1>, std::layout_right> x);
void compute(std::mdspan<float, std::dims<1>> x) {constexpr auto byte_alignment = 4 * sizeof(float); auto accessor = std::aligned_accessor<float, byte_alignment>{}; auto x_handle = x.data_handle(); if (std::is_sufficiently_aligned<byte_alignment>(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<class OtherElementType, size_t OtherByteAlignment>
constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) 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<OtherElementType(*)[], element_type(*)[]> 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<class OtherElementType>
constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;
`
[3](#mdspan.accessor.aligned.members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24567)
*Constraints*: is_convertible_v<OtherElementType(*)[], element_type(*)[]> 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<byte_alignment>(p)[i];
[🔗](#lib:operator_default_accessor,aligned_accessor)
`template<class OtherElementType>
constexpr operator default_accessor<OtherElementType>() const noexcept;
`
[7](#mdspan.accessor.aligned.members-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24599)
*Constraints*: is_convertible_v<element_type(*)[], OtherElementType(*)[]> 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<byte_alignment>(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 ElementType, class Extents, class LayoutPolicy = layout_right, class AccessorPolicy = default_accessor<ElementType>>class mdspan {public:using extents_type = Extents; using layout_type = LayoutPolicy; using accessor_type = AccessorPolicy; using mapping_type = typename layout_type::template mapping<extents_type>; using element_type = ElementType; using value_type = remove_cv_t<element_type>; 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.2Constructors"), constructorsconstexpr mdspan(); constexpr mdspan(const mdspan& rhs) = default; constexpr mdspan(mdspan&& rhs) = default; template<class... OtherIndexTypes>constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts); template<class OtherIndexType, size_t N>constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span<OtherIndexType, N> exts); template<class OtherIndexType, size_t N>constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array<OtherIndexType, N>& 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); template<class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessorPolicy>constexpr explicit(*see below*) mdspan(const mdspan<OtherElementType, OtherExtents,
OtherLayoutPolicy, OtherAccessorPolicy>& other); constexpr mdspan& operator=(const mdspan& rhs) = default; constexpr mdspan& operator=(mdspan&& rhs) = default; // [[mdspan.mdspan.members]](#mdspan.mdspan.members "23.7.3.6.3Members"), memberstemplate<class... OtherIndexTypes>constexpr reference operator[](OtherIndexTypes... indices) const; template<class OtherIndexType>constexpr reference operator[](span<OtherIndexType, rank()> indices) const; template<class OtherIndexType>constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const; template<class... OtherIndexTypes>constexpr reference
at(OtherIndexTypes... indices) const; // freestanding-deletedtemplate<class OtherIndexType>constexpr reference
at(span<OtherIndexType, rank()> indices) const; // freestanding-deletedtemplate<class OtherIndexType>constexpr reference
at(const array<OtherIndexType, rank()>& 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*}; template<class CArray>requires (is_array_v<CArray> && rank_v<CArray> == 1) mdspan(CArray&)-> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>; template<class Pointer>requires (is_pointer_v<remove_reference_t<Pointer>>) mdspan(Pointer&&)-> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>; template<class ElementType, class... Integrals>requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)explicit mdspan(ElementType*, Integrals...)-> mdspan<ElementType, extents<size_t, [*maybe-static-ext*](span.syn#concept:maybe-static-ext "23.7.2.1Header <span> synopsis[span.syn]")<Integrals>...>>; template<class ElementType, class OtherIndexType, size_t N> mdspan(ElementType*, span<OtherIndexType, N>)-> mdspan<ElementType, dextents<size_t, N>>; template<class ElementType, class OtherIndexType, size_t N> mdspan(ElementType*, const array<OtherIndexType, N>&)-> mdspan<ElementType, dextents<size_t, N>>; template<class ElementType, class IndexType, size_t... ExtentsPack> mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)-> mdspan<ElementType, extents<IndexType, ExtentsPack...>>; template<class ElementType, class MappingType> mdspan(ElementType*, const MappingType&)-> mdspan<ElementType, typename MappingType::extents_type, typename MappingType::layout_type>; template<class MappingType, class AccessorType> mdspan(const typename AccessorType::data_handle_type&, const MappingType&, const AccessorType&)-> mdspan<typename AccessorType::element_type, typename MappingType::extents_type, typename MappingType::layout_type, AccessorType>;}
[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<ElementType, typename AccessorPolicy::element_type> 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.3Layout mapping policy requirements")), andAccessorPolicy shall meet
the accessor policy requirements ([[mdspan.accessor.reqmts]](#mdspan.accessor.reqmts "23.7.3.5.2Requirements"))[.](#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.6Object concepts[concepts.object]") and
- [(4.1)](#mdspan.mdspan.overview-4.1)
is_nothrow_move_constructible_v<MDS> is true,
- [(4.2)](#mdspan.mdspan.overview-4.2)
is_nothrow_move_assignable_v<MDS> is true, and
- [(4.3)](#mdspan.mdspan.overview-4.3)
is_nothrow_swappable_v<MDS> 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<data_handle_type> is true[.](#mdspan.mdspan.cons-1.2.sentence-1)
- [(1.3)](#mdspan.mdspan.cons-1.3)
is_default_constructible_v<mapping_type> is true[.](#mdspan.mdspan.cons-1.3.sentence-1)
- [(1.4)](#mdspan.mdspan.cons-1.4)
is_default_constructible_v<accessor_type> 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<class... OtherIndexTypes>
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<OtherIndexTypes, index_type> && ...) is true,
- [(5.2)](#mdspan.mdspan.cons-5.2)
(is_nothrow_constructible<index_type, OtherIndexTypes> && ...) 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<mapping_type, extents_type> is true, and
- [(5.5)](#mdspan.mdspan.cons-5.5)
is_default_constructible_v<accessor_type> 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<index_type>(std::move(exts))...), and
- [(7.3)](#mdspan.mdspan.cons-7.3)
value-initializes *acc_*[.](#mdspan.mdspan.cons-7.sentence-1)
[🔗](#lib:mdspan,constructor__)
`template<class OtherIndexType, size_t N>
constexpr explicit(N != rank_dynamic())
mdspan(data_handle_type p, span<OtherIndexType, N> exts);
template<class OtherIndexType, size_t N>
constexpr explicit(N != rank_dynamic())
mdspan(data_handle_type p, const array<OtherIndexType, N>& 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<const OtherIndexType&, index_type> is true,
- [(8.2)](#mdspan.mdspan.cons-8.2)
is_nothrow_constructible_v<index_type, const OtherIndexType&> 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<mapping_type, extents_type> is true, and
- [(8.5)](#mdspan.mdspan.cons-8.5)
is_default_constructible_v<accessor_type> 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<mapping_type, const extents_type&> is true, and
- [(11.2)](#mdspan.mdspan.cons-11.2)
is_default_constructible_v<accessor_type> 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<accessor_type> 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<class OtherElementType, class OtherExtents,
class OtherLayoutPolicy, class OtherAccessor>
constexpr explicit(see below)
mdspan(const mdspan<OtherElementType, OtherExtents,
OtherLayoutPolicy, OtherAccessor>& 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<mapping_type, const OtherLayoutPolicy::template mapping<Oth-
erExtents>&> is true, and
- [(19.2)](#mdspan.mdspan.cons-19.2)
is_constructible_v<accessor_type, const OtherAccessor&> 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<data_handle_type, const OtherAccessor::data_handle_type&> is
true, and
- [(20.2)](#mdspan.mdspan.cons-20.2)
is_constructible_v<extents_type, OtherExtents> 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<const OtherLayoutPolicy::template mapping<OtherExtents>&, mapping_type>|| !is_convertible_v<const OtherAccessor&, accessor_type>
#### [23.7.3.6.3](#mdspan.mdspan.members) Members [[mdspan.mdspan.members]](mdspan.mdspan.members)
[🔗](#lib:operator%5b%5d,mdspan)
`template<class... OtherIndexTypes>
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<OtherIndexTypes, index_type> && ...) is true,
- [(1.2)](#mdspan.mdspan.members-1.2)
(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) 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<index_type>(std::move(indices))...));
[🔗](#lib:operator%5b%5d,mdspan_)
`template<class OtherIndexType>
constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
template<class OtherIndexType>
constexpr reference operator[](const array<OtherIndexType, rank()>& 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<const OtherIndexType&, index_type> is true, and
- [(5.2)](#mdspan.mdspan.members-5.2)
is_nothrow_constructible_v<index_type, const OtherIndexType&> 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<make_index_sequence<rank()>, index_sequence<P...>> is true[.](#mdspan.mdspan.members-6.sentence-1)
Equivalent to:return operator[](extents_type::*index-cast*(as_const(indices[P]))...);
[🔗](#lib:at,mdspan)
`template<class... OtherIndexTypes>
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<OtherIndexTypes, index_type> && ...) is true,
- [(7.2)](#mdspan.mdspan.members-7.2)
(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) 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<class OtherIndexType>
constexpr reference at(span<OtherIndexType, rank()> indices) const;
template<class OtherIndexType>
constexpr reference at(const array<OtherIndexType, rank()>& 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<const OtherIndexType&, index_type> is true, and
- [(11.2)](#mdspan.mdspan.members-11.2)
is_nothrow_constructible_v<index_type, const OtherIndexType&> 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<make_index_sequence<rank()>, index_sequence<P...>> 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.2Fundamental 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.7submdspan") 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<decltype(src)>::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<size_t, rank> 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.4Concept convertible_­to[concept.convertible]")<index_type>,
* [(2.5.2)](#mdspan.sub.overview-2.5.2)
otherwise,
the number of types Sj with j<k that
do not model [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<index_type>[.](#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 {template<class OffsetType, class ExtentType, class StrideType>struct 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*](span.syn#concept:integral-constant-like "23.7.2.1Header <span> 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 {template<class LayoutMapping>struct 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.3Layout 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<class T>
constexpr T de-ice(T val) { return val; }
template<[integral-constant-like](span.syn#concept:integral-constant-like "23.7.2.1Header <span> synopsis[span.syn]") T>
constexpr auto de-ice(T) { return T::value; }
template<class IndexType, size_t k, class... SliceSpecifiers>
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.4Concept convertible_­to[concept.convertible]")<IndexType>;
- [(2.2)](#mdspan.sub.helpers-2.2)
otherwise,get<0>(sk) if Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2Header <mdspan> synopsis[mdspan.syn]")<IndexType>;
- [(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<IndexType>::*index-cast*(ϕk)[.](#mdspan.sub.helpers-4.sentence-1)
[🔗](#lib:last_)
`template<size_t k, class Extents, class... SliceSpecifiers>
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.4Concept convertible_­to[concept.convertible]")<index_type>; otherwise
- [(7.2)](#mdspan.sub.helpers-7.2)
get<1>(sk) if Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2Header <mdspan> synopsis[mdspan.syn]")<index_type>; 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<class IndexType, size_t N, class... SliceSpecifiers>
constexpr array<IndexType, sizeof...(SliceSpecifiers)>
src-indices(const array<IndexType, N>& 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<IndexType, sizeof...(SliceSpecifiers)> 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_*<IndexType, k>(slices...) for each k where *map-rank*[k] equalsdynamic_extent,
- [(11.2)](#mdspan.sub.helpers-11.2)
otherwise,*first_*<IndexType, k>(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<class IndexType, size_t... Extents, class... SliceSpecifiers>
constexpr auto submdspan_extents(const extents<IndexType, 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.4Concept convertible_­to[concept.convertible]")<IndexType>,
- [(2.2)](#mdspan.sub.extents-2.2)
Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2Header <mdspan> synopsis[mdspan.syn]")<IndexType>,
- [(2.3)](#mdspan.sub.extents-2.3)
is_convertible_v<Sk, full_extent_t> 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_*<IndexType, k>(slices...) ≤ *last_*<k>(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.4Concept convertible_­to[concept.convertible]")<IndexType>; 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<Sk, full_extent_t> 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.2Header <mdspan> synopsis[mdspan.syn]")<IndexType>, and
both tuple_element_t<0, Sk> and tuple_element_t<1, Sk> model [*integral-constant-like*](span.syn#concept:integral-constant-like "23.7.2.1Header <span> 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_*<k>(src, slices...) - *first_*<IndexType, k>(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.6Specializations 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.4Concept convertible_­to[concept.convertible]")<index_type>,
- [(3.2)](#mdspan.sub.map.common-3.2)
Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2Header <mdspan> synopsis[mdspan.syn]")<index_type>,
- [(3.3)](#mdspan.sub.map.common-3.3)
is_convertible_v<Sk, full_extent_t> 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_*<index_type, k>(slices...)
0 ≤ *last_*<k>(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<SubExtents::index_type, SubExtents::rank()> 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<make_index_sequence<rank()>, index_sequence<P...>> 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_*<index_type, k>(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_*<index_type, P>(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.1Common[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*](span.syn#concept:integral-constant-like "23.7.2.1Header <span> 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.2Header <mdspan> synopsis[mdspan.syn]")<M::index_type>, or
- [(9.3)](#mdspan.sub.map.common-9.3)
is_convertible_v<S, full_extent_t> 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<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_left::mapping<Extents>::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<Sk, full_extent_t> 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<S_static>::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<Sk, full_extent_t> 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<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_right::mapping<Extents>::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<Sk, full_extent_t> 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<S_static>::mapping(sub_ext,
stride(*rank_* - u - 2)), offset} if for a value u for which rank_−ˆ’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<Sk, full_extent_t> 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<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_stride::mapping<Extents>::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<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_left_padded::mapping<Extents>::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<S_static>::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<Sk, full_extent_t> 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<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_right_padded::mapping<Extents>::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<S_static>::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<Sk, full_extent_t> 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<class ElementType, class Extents, class LayoutPolicy,
class AccessorPolicy, class... SliceSpecifiers>
constexpr auto submdspan(
const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& 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.4Argument-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<remove_cvref_t<decltype(sub_map_offset.mapping.extents())>,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.4Concept convertible_­to[concept.convertible]")<index_type>,
* [(4.3.2)](#mdspan.sub.sub-4.3.2)
Sk models [*index-pair-like*](#concept:index-pair-like "23.7.3.2Header <mdspan> synopsis[mdspan.syn]")<index_type>,
* [(4.3.3)](#mdspan.sub.sub-4.3.3)
is_convertible_v<Sk, full_extent_t> 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_*<index_type, k>(slices...) ≤ *last_*<k>(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 mdspantemplate<class T, class E, class L, class A>void zero_2d(mdspan<T, E, L, A> 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 surfacetemplate<class T, class E, class L, class A>void zero_surface(mdspan<T, E, L, A> 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*]