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

2694 lines
103 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.

[mdspan.layout]
# 23 Containers library [[containers]](./#containers)
## 23.7 Views [[views]](views#mdspan.layout)
### 23.7.3 Multidimensional access [[views.multidim]](views.multidim#mdspan.layout)
#### 23.7.3.4 Layout mapping [mdspan.layout]
#### [23.7.3.4.1](#general) General [[mdspan.layout.general]](mdspan.layout.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21522)
In [[mdspan.layout.reqmts]](#reqmts "23.7.3.4.2Requirements") and [[mdspan.layout.policy.reqmts]](#policy.reqmts "23.7.3.4.3Layout mapping policy requirements"):
- [(1.1)](#general-1.1)
M denotes a layout mapping class[.](#general-1.1.sentence-1)
- [(1.2)](#general-1.2)
m denotes a (possibly const) value of type M[.](#general-1.2.sentence-1)
- [(1.3)](#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"))[.](#general-1.3.sentence-1)
[*Note [1](#general-note-1)*:
The type of each element of the packs can be a different integer type[.](#general-1.3.sentence-2)
— *end note*]
- [(1.4)](#general-1.4)
r is a (possibly const) rank index of typename M::extents_type[.](#general-1.4.sentence-1)
- [(1.5)](#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[.](#general-1.5.sentence-1)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21549)
In [[mdspan.layout.reqmts]](#reqmts "23.7.3.4.2Requirements") through [[mdspan.layout.stride]](#stride "23.7.3.4.7Class template layout_­stride::mapping"):
- [(2.1)](#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)](#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)](#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)](#general-2.4)
For nonnegative integers x and y,
let LEAST-MULTIPLE-AT-LEAST(x,y) denote
* [(2.4.1)](#general-2.4.1)
y if x is zero,
* [(2.4.2)](#general-2.4.2)
otherwise, the least multiple of x that is greater than or equal to y.
#### [23.7.3.4.2](#reqmts) Requirements [[mdspan.layout.reqmts]](mdspan.layout.reqmts)
[1](#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)](#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)](#reqmts-1.2)
is_nothrow_move_constructible_v<M> is true,
- [(1.3)](#reqmts-1.3)
is_nothrow_move_assignable_v<M> is true,
- [(1.4)](#reqmts-1.4)
is_nothrow_swappable_v<M> is true, and
- [(1.5)](#reqmts-1.5)
the following types and expressions are well-formed and
have the specified semantics.
[🔗](#reqmts-itemdecl:1)
`typename M::extents_type
`
[2](#reqmts-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21616)
*Result*: A type that is a specialization of extents[.](#reqmts-2.sentence-1)
[🔗](#reqmts-itemdecl:2)
`typename M::index_type
`
[3](#reqmts-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21626)
*Result*: typename M::extents_type::index_type[.](#reqmts-3.sentence-1)
[🔗](#reqmts-itemdecl:3)
`typename M::rank_type
`
[4](#reqmts-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21636)
*Result*: typename M::extents_type::rank_type[.](#reqmts-4.sentence-1)
[🔗](#reqmts-itemdecl:4)
`typename M::layout_type
`
[5](#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]](#policy.reqmts "23.7.3.4.3Layout mapping policy requirements")) and
for which *is-mapping-of*<MP, M> is true[.](#reqmts-5.sentence-1)
[🔗](#reqmts-itemdecl:5)
`m.extents()
`
[6](#reqmts-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21658)
*Result*: const typename M::extents_type&
[🔗](#reqmts-itemdecl:6)
`m(i...)
`
[7](#reqmts-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21668)
*Result*: typename M::index_type
[8](#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()[.](#reqmts-8.sentence-1)
[🔗](#reqmts-itemdecl:7)
`m(i...) == m(static_cast<typename M::index_type>(i)...)
`
[9](#reqmts-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21684)
*Result*: bool
[10](#reqmts-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21688)
*Returns*: true
[🔗](#reqmts-itemdecl:8)
`m.required_span_size()
`
[11](#reqmts-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21698)
*Result*: typename M::index_type
[12](#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[.](#reqmts-12.sentence-1)
[🔗](#reqmts-itemdecl:9)
`m.is_unique()
`
[13](#reqmts-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21714)
*Result*: bool
[14](#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[.](#reqmts-14.sentence-1)
[*Note [1](#reqmts-note-1)*:
A mapping can return false even if the condition is met[.](#reqmts-14.sentence-2)
For certain layouts, it is possibly not feasible to determine efficiently
whether the layout is unique[.](#reqmts-14.sentence-3)
— *end note*]
[🔗](#reqmts-itemdecl:10)
`m.is_exhaustive()
`
[15](#reqmts-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21735)
*Result*: bool
[16](#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[.](#reqmts-16.sentence-1)
[*Note [2](#reqmts-note-2)*:
A mapping can return false even if the condition is met[.](#reqmts-16.sentence-2)
For certain layouts, it is possibly not feasible to determine efficiently
whether the layout is exhaustive[.](#reqmts-16.sentence-3)
— *end note*]
[🔗](#reqmts-itemdecl:11)
`m.is_strided()
`
[17](#reqmts-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21756)
*Result*: bool
[18](#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[.](#reqmts-18.sentence-1)
[*Note [3](#reqmts-note-3)*:
This implies that for a strided layoutm(i0,…,ik)=m(0,…,0)+i0×s0+⋯+ik×sk[.](#reqmts-18.sentence-2)
— *end note*]
[*Note [4](#reqmts-note-4)*:
A mapping can return false even if the condition is met[.](#reqmts-18.sentence-3)
For certain layouts, it is possibly not feasible to determine efficiently
whether the layout is strided[.](#reqmts-18.sentence-4)
— *end note*]
[🔗](#reqmts-itemdecl:12)
`m.stride(r)
`
[19](#reqmts-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21784)
*Preconditions*: m.is_strided() is true[.](#reqmts-19.sentence-1)
[20](#reqmts-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21788)
*Result*: typename M::index_type
[21](#reqmts-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21792)
*Returns*: sr as defined in m.is_strided() above[.](#reqmts-21.sentence-1)
[22](#reqmts-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21796)
[*Note [5](#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[.](#reqmts-22.sentence-1)
— *end note*]
[🔗](#reqmts-itemdecl:13)
`M::is_always_unique()
`
[23](#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[.](#reqmts-23.sentence-1)
[24](#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[.](#reqmts-24.sentence-1)
[*Note [6](#reqmts-note-6)*:
A mapping can return false even if the above condition is met[.](#reqmts-24.sentence-2)
For certain layout mappings, it is possibly not feasible to determine
whether every instance is unique[.](#reqmts-24.sentence-3)
— *end note*]
[🔗](#reqmts-itemdecl:14)
`M::is_always_exhaustive()
`
[25](#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[.](#reqmts-25.sentence-1)
[26](#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[.](#reqmts-26.sentence-1)
[*Note [7](#reqmts-note-7)*:
A mapping can return false even if the above condition is met[.](#reqmts-26.sentence-2)
For certain layout mappings, it is possibly not feasible to determine
whether every instance is exhaustive[.](#reqmts-26.sentence-3)
— *end note*]
[🔗](#reqmts-itemdecl:15)
`M::is_always_strided()
`
[27](#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[.](#reqmts-27.sentence-1)
[28](#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[.](#reqmts-28.sentence-1)
[*Note [8](#reqmts-note-8)*:
A mapping can return false even if the above condition is met[.](#reqmts-28.sentence-2)
For certain layout mappings, it is possibly not feasible to determine
whether every instance is strided[.](#reqmts-28.sentence-3)
— *end note*]
#### [23.7.3.4.3](#policy.reqmts) Layout mapping policy requirements [[mdspan.layout.policy.reqmts]](mdspan.layout.policy.reqmts)
[1](#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]](#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[.](#policy.reqmts-1.sentence-1)
#### [23.7.3.4.4](#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](#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[.](#policy.overview-1.sentence-1)
Furthermore,is_trivially_default_constructible_v<T> is true for any such type T[.](#policy.overview-1.sentence-2)
#### [23.7.3.4.5](#left) Class template layout_left::mapping [[mdspan.layout.left]](mdspan.layout.left)
#### [23.7.3.4.5.1](#left.overview) Overview [[mdspan.layout.left.overview]](mdspan.layout.left.overview)
[1](#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[.](#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]](#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]](#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](#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[.](#left.overview-2.sentence-1)
[3](#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[.](#left.overview-3.sentence-1)
[4](#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[.](#left.overview-4.sentence-1)
#### [23.7.3.4.5.2](#left.cons) Constructors [[mdspan.layout.left.cons]](mdspan.layout.left.cons)
[🔗](#lib:layout_left::mapping,constructor)
`constexpr mapping(const extents_type& e) noexcept;
`
[1](#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"))[.](#left.cons-1.sentence-1)
[2](#left.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22017)
*Effects*: Direct-non-list-initializes *extents_* with e[.](#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](#left.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22030)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#left.cons-3.sentence-1)
[4](#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"))[.](#left.cons-4.sentence-1)
[5](#left.cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22039)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#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](#left.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22052)
*Constraints*:
- [(6.1)](#left.cons-6.1)
extents_type::rank() <= 1 is true, and
- [(6.2)](#left.cons-6.2)
is_constructible_v<extents_type, OtherExtents> is true[.](#left.cons-6.sentence-1)
[7](#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"))[.](#left.cons-7.sentence-1)
[8](#left.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22066)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#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](#left.cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22080)
*Constraints*:
- [(9.1)](#left.cons-9.1)
*is-layout-left-padded-mapping-of*<LayoutLeftPaddedMapping> is true[.](#left.cons-9.1.sentence-1)
- [(9.2)](#left.cons-9.2)
is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>
is true[.](#left.cons-9.2.sentence-1)
[10](#left.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22089)
*Mandates*: If
- [(10.1)](#left.cons-10.1)
Extents::rank() is greater than one,
- [(10.2)](#left.cons-10.2)
Extents::static_extent(0) does not equal dynamic_extent, and
- [(10.3)](#left.cons-10.3)
LayoutLeftPaddedMapping::*static-padding-stride* does not equal dynamic_extent,
then Extents::static_extent(0) equalsLayoutLeftPaddedMapping::*static-padding-stride*[.](#left.cons-10.sentence-1)
[11](#left.cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22104)
*Preconditions*:
- [(11.1)](#left.cons-11.1)
If extents_type::rank() > 1 is true,
then other.stride(1) equals other.extents(0)[.](#left.cons-11.1.sentence-1)
- [(11.2)](#left.cons-11.2)
other.required_span_size() is representable as
a value of type index_type[.](#left.cons-11.2.sentence-1)
[12](#left.cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22115)
*Effects*: Direct-non-list-initializes extents_ with other.extents()[.](#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](#left.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22128)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#left.cons-13.sentence-1)
[14](#left.cons-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22132)
*Preconditions*:
- [(14.1)](#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)](#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"))[.](#left.cons-14.sentence-1)
[15](#left.cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22145)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#left.cons-15.sentence-1)
#### [23.7.3.4.5.3](#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](#left.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22158)
*Returns*: extents().*fwd-prod-of-extents*(extents_type::rank())[.](#left.obs-1.sentence-1)
[🔗](#lib:operator(),layout_left::mapping)
`template<class... Indices>
constexpr index_type operator()(Indices... i) const noexcept;
`
[2](#left.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22170)
*Constraints*:
- [(2.1)](#left.obs-2.1)
sizeof...(Indices) == extents_type::rank() is true,
- [(2.2)](#left.obs-2.2)
(is_convertible_v<Indices, index_type> && ...) is true, and
- [(2.3)](#left.obs-2.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) is true[.](#left.obs-2.sentence-1)
[3](#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"))[.](#left.obs-3.sentence-1)
[4](#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[.](#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](#left.obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22205)
*Constraints*: extents_type::rank() > 0 is true[.](#left.obs-5.sentence-1)
[6](#left.obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22209)
*Preconditions*: i < extents_type::rank() is true[.](#left.obs-6.sentence-1)
[7](#left.obs-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22213)
*Returns*: extents().*fwd-prod-of-extents*(i)[.](#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](#left.obs-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22225)
*Constraints*: extents_type::rank() == OtherExtents::rank() is true[.](#left.obs-8.sentence-1)
[9](#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](#right) Class template layout_right::mapping [[mdspan.layout.right]](mdspan.layout.right)
#### [23.7.3.4.6.1](#right.overview) Overview [[mdspan.layout.right.overview]](mdspan.layout.right.overview)
[1](#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[.](#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]](#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]](#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](#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[.](#right.overview-2.sentence-1)
[3](#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[.](#right.overview-3.sentence-1)
[4](#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[.](#right.overview-4.sentence-1)
#### [23.7.3.4.6.2](#right.cons) Constructors [[mdspan.layout.right.cons]](mdspan.layout.right.cons)
[🔗](#lib:layout_right::mapping,constructor)
`constexpr mapping(const extents_type& e) noexcept;
`
[1](#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"))[.](#right.cons-1.sentence-1)
[2](#right.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22339)
*Effects*: Direct-non-list-initializes *extents_* with e[.](#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](#right.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22352)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#right.cons-3.sentence-1)
[4](#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"))[.](#right.cons-4.sentence-1)
[5](#right.cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22361)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#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](#right.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22374)
*Constraints*:
- [(6.1)](#right.cons-6.1)
extents_type::rank() <= 1 is true, and
- [(6.2)](#right.cons-6.2)
is_constructible_v<extents_type, OtherExtents> is true[.](#right.cons-6.sentence-1)
[7](#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"))[.](#right.cons-7.sentence-1)
[8](#right.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22388)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#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](#right.cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22402)
*Constraints*:
- [(9.1)](#right.cons-9.1)
*is-layout-right-padded-mapping-of*<LayoutRightPaddedMapping> is true[.](#right.cons-9.1.sentence-1)
- [(9.2)](#right.cons-9.2)
is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type> is true[.](#right.cons-9.2.sentence-1)
[10](#right.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22413)
*Mandates*: If
- [(10.1)](#right.cons-10.1)
Extents::rank() is greater than one,
- [(10.2)](#right.cons-10.2)
Extents::static_extent(Extents::rank() - 1) does not equal dynamic_extent, and
- [(10.3)](#right.cons-10.3)
LayoutRightPaddedMapping::*static-padding-stride* does not equal dynamic_extent,
then Extents::static_extent(Extents::rank() - 1) equalsLayoutRightPaddedMapping::*static-padding-stride*[.](#right.cons-10.sentence-1)
[11](#right.cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22429)
*Preconditions*:
- [(11.1)](#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)[.](#right.cons-11.1.sentence-1)
- [(11.2)](#right.cons-11.2)
other.required_span_size() is representable as
a value of type index_type[.](#right.cons-11.2.sentence-1)
[12](#right.cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22441)
*Effects*: Direct-non-list-initializes extents_ with other.extents()[.](#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](#right.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22454)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#right.cons-13.sentence-1)
[14](#right.cons-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22458)
*Preconditions*:
- [(14.1)](#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)[.](#right.cons-14.1.sentence-1)
- [(14.2)](#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"))[.](#right.cons-14.2.sentence-1)
[15](#right.cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22471)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#right.cons-15.sentence-1)
#### [23.7.3.4.6.3](#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](#right.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22484)
*Returns*: extents().*fwd-prod-of-extents*(extents_type::rank())[.](#right.obs-1.sentence-1)
[🔗](#lib:operator(),layout_right::mapping)
`template<class... Indices>
constexpr index_type operator()(Indices... i) const noexcept;
`
[2](#right.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22496)
*Constraints*:
- [(2.1)](#right.obs-2.1)
sizeof...(Indices) == extents_type::rank() is true,
- [(2.2)](#right.obs-2.2)
(is_convertible_v<Indices, index_type> && ...) is true, and
- [(2.3)](#right.obs-2.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) istrue[.](#right.obs-2.sentence-1)
[3](#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"))[.](#right.obs-3.sentence-1)
[4](#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[.](#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](#right.obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22531)
*Constraints*: extents_type::rank() > 0 is true[.](#right.obs-5.sentence-1)
[6](#right.obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22535)
*Preconditions*: i < extents_type::rank() is true[.](#right.obs-6.sentence-1)
[7](#right.obs-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22539)
*Returns*: extents().*rev-prod-of-extents*(i)[.](#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](#right.obs-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22551)
*Constraints*: extents_type::rank() == OtherExtents::rank() is true[.](#right.obs-8.sentence-1)
[9](#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](#stride) Class template layout_stride::mapping [[mdspan.layout.stride]](mdspan.layout.stride)
#### [23.7.3.4.7.1](#stride.overview) Overview [[mdspan.layout.stride.overview]](mdspan.layout.stride.overview)
[1](#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[.](#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]](#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]](#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](#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[.](#stride.overview-2.sentence-1)
[3](#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[.](#stride.overview-3.sentence-1)
[4](#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[.](#stride.overview-4.sentence-1)
#### [23.7.3.4.7.2](#stride.expo) Exposition-only helpers [[mdspan.layout.stride.expo]](mdspan.layout.stride.expo)
[1](#stride.expo-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22652)
Let *REQUIRED-SPAN-SIZE*(e, strides) be:
- [(1.1)](#stride.expo-1.1)
1, if e.rank() == 0 is true,
- [(1.2)](#stride.expo-1.2)
otherwise 0, if the size of the multidimensional index space e is 0,
- [(1.3)](#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())[.](#stride.expo-1.sentence-1)
[2](#stride.expo-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22668)
Let *OFFSET*(m) be:
- [(2.1)](#stride.expo-2.1)
m(), if e.rank() == 0 is true,
- [(2.2)](#stride.expo-2.2)
otherwise 0, if the size of the multidimensional index space e is 0,
- [(2.3)](#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[.](#stride.expo-2.sentence-1)
[3](#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](#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](#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[.](#stride.expo-4.sentence-1)
— *end note*]
#### [23.7.3.4.7.3](#stride.cons) Constructors [[mdspan.layout.stride.cons]](mdspan.layout.stride.cons)
[🔗](#lib:layout_stride::mapping,constructor)
`constexpr mapping() noexcept;
`
[1](#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"))[.](#stride.cons-1.sentence-1)
[2](#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)[.](#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](#stride.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22745)
*Constraints*:
- [(3.1)](#stride.cons-3.1)
is_convertible_v<const OtherIndexType&, index_type> is true, and
- [(3.2)](#stride.cons-3.2)
is_nothrow_constructible_v<index_type, const OtherIndexType&> is true[.](#stride.cons-3.sentence-1)
[4](#stride.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22754)
*Preconditions*:
- [(4.1)](#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_*)[.](#stride.cons-4.1.sentence-1)
- [(4.2)](#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"))[.](#stride.cons-4.2.sentence-1)
- [(4.3)](#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[.](#stride.cons-4.3.sentence-1)
[*Note [1](#stride.cons-note-1)*:
For layout_stride,
this condition is necessary and sufficient
for is_unique() to be true[.](#stride.cons-4.3.sentence-2)
— *end note*]
[5](#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])[.](#stride.cons-5.sentence-1)
[🔗](#lib:layout_stride::mapping,constructor__)
`template<class StridedLayoutMapping>
constexpr explicit(see below)
mapping(const StridedLayoutMapping& other) noexcept;
`
[6](#stride.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22793)
*Constraints*:
- [(6.1)](#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[.](#stride.cons-6.1.sentence-1)
- [(6.2)](#stride.cons-6.2)
is_constructible_v<extents_type, typename StridedLayoutMapping::extents_type> is
true[.](#stride.cons-6.2.sentence-2)
- [(6.3)](#stride.cons-6.3)
StridedLayoutMapping::is_always_unique() is true[.](#stride.cons-6.3.sentence-1)
- [(6.4)](#stride.cons-6.4)
StridedLayoutMapping::is_always_strided() is true[.](#stride.cons-6.4.sentence-1)
[7](#stride.cons-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22806)
*Preconditions*:
- [(7.1)](#stride.cons-7.1)
StridedLayoutMapping meets the layout mapping requirements ([[mdspan.layout.reqmts]](#reqmts "23.7.3.4.2Requirements")),
- [(7.2)](#stride.cons-7.2)
other.stride(r) > 0 is true for every rank index r of extents(),
- [(7.3)](#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)](#stride.cons-7.4)
*OFFSET*(other) == 0 is true[.](#stride.cons-7.sentence-1)
[8](#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)[.](#stride.cons-8.sentence-1)
[9](#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](#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](#stride.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22848)
*Returns*: *REQUIRED-SPAN-SIZE*(extents(), *strides_*)[.](#stride.obs-1.sentence-1)
[🔗](#lib:operator(),layout_stride::mapping)
`template<class... Indices>
constexpr index_type operator()(Indices... i) const noexcept;
`
[2](#stride.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22860)
*Constraints*:
- [(2.1)](#stride.obs-2.1)
sizeof...(Indices) == *rank_* is true,
- [(2.2)](#stride.obs-2.2)
(is_convertible_v<Indices, index_type> && ...) is true, and
- [(2.3)](#stride.obs-2.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) is true[.](#stride.obs-2.sentence-1)
[3](#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"))[.](#stride.obs-3.sentence-1)
[4](#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[.](#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](#stride.obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22895)
*Returns*:
- [(5.1)](#stride.obs-5.1)
true if *rank_* is 0[.](#stride.obs-5.1.sentence-1)
- [(5.2)](#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[.](#stride.obs-5.2.sentence-1)
- [(5.3)](#stride.obs-5.3)
Otherwise, false[.](#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](#stride.obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22919)
*Constraints*:
- [(6.1)](#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[.](#stride.obs-6.1.sentence-1)
- [(6.2)](#stride.obs-6.2)
*rank_* == OtherMapping::extents_type::rank() is true[.](#stride.obs-6.2.sentence-1)
- [(6.3)](#stride.obs-6.3)
OtherMapping::is_always_strided() is true[.](#stride.obs-6.3.sentence-1)
[7](#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]](#policy.reqmts "23.7.3.4.3Layout mapping policy requirements"))[.](#stride.obs-7.sentence-1)
[8](#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())[.](#stride.obs-8.sentence-1)
Otherwise, false[.](#stride.obs-8.sentence-2)
#### [23.7.3.4.8](#leftpad) Class template layout_left_padded::mapping [[mdspan.layout.leftpad]](mdspan.layout.leftpad)
#### [23.7.3.4.8.1](#leftpad.overview) Overview [[mdspan.layout.leftpad.overview]](mdspan.layout.leftpad.overview)
[1](#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)[.](#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]](#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]](#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]](#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]](#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](#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[.](#leftpad.overview-2.sentence-1)
[3](#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[.](#leftpad.overview-3.sentence-1)
[4](#leftpad.overview-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23043)
Throughout [[mdspan.layout.leftpad]](#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)](#leftpad.overview-4.1)
the empty parameter pack, if *rank_* equals zero;
- [(4.2)](#leftpad.overview-4.2)
otherwise, 0zu, if *rank_* equals one;
- [(4.3)](#leftpad.overview-4.3)
otherwise, the parameter pack 0zu, 1zu, …, *rank_*- 1[.](#leftpad.overview-4.sentence-1)
[5](#leftpad.overview-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23056)
*Mandates*:
- [(5.1)](#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[.](#leftpad.overview-5.1.sentence-1)
- [(5.2)](#leftpad.overview-5.2)
padding_value is representable as a value of type index_type[.](#leftpad.overview-5.2.sentence-1)
- [(5.3)](#leftpad.overview-5.3)
If
* [(5.3.1)](#leftpad.overview-5.3.1)
*rank_* is greater than one,
* [(5.3.2)](#leftpad.overview-5.3.2)
padding_value does not equal dynamic_extent, and
* [(5.3.3)](#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[.](#leftpad.overview-5.3.sentence-1)
- [(5.4)](#leftpad.overview-5.4)
If
* [(5.4.1)](#leftpad.overview-5.4.1)
*rank_* is greater than one,
* [(5.4.2)](#leftpad.overview-5.4.2)
padding_value does not equal dynamic_extent, and
* [(5.4.3)](#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[.](#leftpad.overview-5.4.sentence-1)
#### [23.7.3.4.8.2](#leftpad.expo) Exposition-only members [[mdspan.layout.leftpad.expo]](mdspan.layout.leftpad.expo)
[🔗](#leftpad.expo-itemdecl:1)
`static constexpr size_t static-padding-stride = see below;
`
[1](#leftpad.expo-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23104)
The value is
- [(1.1)](#leftpad.expo-1.1)
0, if *rank_* equals zero or one;
- [(1.2)](#leftpad.expo-1.2)
otherwise, dynamic_extent,
if padding_value or *first-static-extent* equalsdynamic_extent;
- [(1.3)](#leftpad.expo-1.3)
otherwise, the size_t value which is*LEAST-MULTIPLE-AT-LEAST*(padding_value, *first-static-extent*)[.](#leftpad.expo-1.sentence-1)
[🔗](#leftpad.expo-itemdecl:2)
`index_type stride-1 = static-padding-stride;
`
[2](#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[.](#leftpad.expo-2.sentence-1)
[*Note [1](#leftpad.expo-note-1)*:
Using extents<index_type, *static-padding-stride*> instead ofindex_type as the type of *stride-1* would achieve this[.](#leftpad.expo-2.sentence-2)
— *end note*]
#### [23.7.3.4.8.3](#leftpad.cons) Constructors [[mdspan.layout.leftpad.cons]](mdspan.layout.leftpad.cons)
[🔗](#lib:layout_left_padded::mapping,constructor)
`constexpr mapping(const extents_type& ext);
`
[1](#leftpad.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23142)
*Preconditions*:
- [(1.1)](#leftpad.cons-1.1)
The size of the multidimensional index space ext is representable as
a value of type index_type[.](#leftpad.cons-1.1.sentence-1)
- [(1.2)](#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*[.](#leftpad.cons-1.2.sentence-1)
- [(1.3)](#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[.](#leftpad.cons-1.3.sentence-1)
[2](#leftpad.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23163)
*Effects*:
- [(2.1)](#leftpad.cons-2.1)
Direct-non-list-initializes *extents_* with ext; and
- [(2.2)](#leftpad.cons-2.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-1*
* [(2.2.1)](#leftpad.cons-2.2.1)
with ext.extent(0) if padding_value is dynamic_extent,
* [(2.2.2)](#leftpad.cons-2.2.2)
otherwise with*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(0))[.](#leftpad.cons-2.sentence-1)
[🔗](#lib:layout_left_padded::mapping,constructor_)
`template<class OtherIndexType>
constexpr mapping(const extents_type& ext, OtherIndexType pad);
`
[3](#leftpad.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23188)
*Constraints*:
- [(3.1)](#leftpad.cons-3.1)
is_convertible_v<OtherIndexType, index_type> is true[.](#leftpad.cons-3.1.sentence-1)
- [(3.2)](#leftpad.cons-3.2)
is_nothrow_constructible_v<index_type, OtherIndexType> is true[.](#leftpad.cons-3.2.sentence-1)
[4](#leftpad.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23197)
*Preconditions*:
- [(4.1)](#leftpad.cons-4.1)
pad is representable as a value of type index_type[.](#leftpad.cons-4.1.sentence-1)
- [(4.2)](#leftpad.cons-4.2)
extents_type::index-cast(pad) is greater than zero[.](#leftpad.cons-4.2.sentence-1)
- [(4.3)](#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)](#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[.](#leftpad.cons-4.4.sentence-1)
- [(4.5)](#leftpad.cons-4.5)
If padding_value is not equal to dynamic_extent,padding_value equals extents_type::*index-cast*(pad)[.](#leftpad.cons-4.5.sentence-1)
[5](#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))[.](#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](#leftpad.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23236)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#leftpad.cons-6.sentence-1)
[7](#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[.](#leftpad.cons-7.sentence-1)
[8](#leftpad.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23250)
*Preconditions*:
- [(8.1)](#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)](#leftpad.cons-8.2)
other.required_span_size() is representable as
a value of type index_type[.](#leftpad.cons-8.sentence-1)
[9](#leftpad.cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23267)
*Effects*: Equivalent to mapping(other.extents())[.](#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](#leftpad.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23280)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#leftpad.cons-10.sentence-1)
[11](#leftpad.cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23284)
*Preconditions*:
- [(11.1)](#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)](#leftpad.cons-11.2)
If *rank_* is greater than 0,
then other.stride(0) equals 1[.](#leftpad.cons-11.2.sentence-1)
- [(11.3)](#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)](#leftpad.cons-11.4)
other.required_span_size() is representable as
a value of type *index_type*[.](#leftpad.cons-11.4.sentence-1)
[12](#leftpad.cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23310)
*Effects*:
- [(12.1)](#leftpad.cons-12.1)
Direct-non-list-initializes *extents_* with other.extents() and
- [(12.2)](#leftpad.cons-12.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-1* withother.stride(1)[.](#leftpad.cons-12.sentence-1)
[🔗](#lib:layout_left_padded::mapping,constructor____)
`template<class LayoutLeftPaddedMapping>
constexpr explicit(see below)
mapping(const LayoutLeftPaddedMapping& other);
`
[13](#leftpad.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23330)
*Constraints*:
- [(13.1)](#leftpad.cons-13.1)
*is-layout-left-padded-mapping-of*<LayoutLeftPaddedMapping> is true[.](#leftpad.cons-13.1.sentence-1)
- [(13.2)](#leftpad.cons-13.2)
is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>
is true[.](#leftpad.cons-13.2.sentence-1)
[14](#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[.](#leftpad.cons-14.sentence-1)
[15](#leftpad.cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23352)
*Preconditions*:
- [(15.1)](#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)](#leftpad.cons-15.2)
other.required_span_size() is representable as
a value of type index_type[.](#leftpad.cons-15.sentence-1)
[16](#leftpad.cons-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23368)
*Effects*:
- [(16.1)](#leftpad.cons-16.1)
Direct-non-list-initializes *extents_* with other.extents() and
- [(16.2)](#leftpad.cons-16.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-1* with other.stride(1)[.](#leftpad.cons-16.sentence-1)
[17](#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](#leftpad.cons-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23396)
*Constraints*:
- [(18.1)](#leftpad.cons-18.1)
*is-layout-right-padded-mapping-of*<LayoutRightPaddedMapping> is true or
*is-mapping-of*<layout_right, LayoutRightPaddedMapping> is true[.](#leftpad.cons-18.1.sentence-1)
- [(18.2)](#leftpad.cons-18.2)
*rank_* equals zero or one[.](#leftpad.cons-18.2.sentence-1)
- [(18.3)](#leftpad.cons-18.3)
is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type> is true[.](#leftpad.cons-18.3.sentence-1)
[19](#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[.](#leftpad.cons-19.sentence-1)
[20](#leftpad.cons-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23416)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#leftpad.cons-20.sentence-1)
[21](#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](#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[.](#leftpad.cons-21.sentence-2)
— *end note*]
#### [23.7.3.4.8.4](#leftpad.obs) Observers [[mdspan.layout.leftpad.obs]](mdspan.layout.leftpad.obs)
[🔗](#leftpad.obs-itemdecl:1)
`constexpr array<index_type, rank_> strides() const noexcept;
`
[1](#leftpad.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23442)
*Returns*: array<index_type, *rank_*>({stride(P_rank)...})[.](#leftpad.obs-1.sentence-1)
[🔗](#leftpad.obs-itemdecl:2)
`constexpr index_type required_span_size() const noexcept;
`
[2](#leftpad.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23452)
*Returns*:
- [(2.1)](#leftpad.obs-2.1)
0 if the multidimensional index space *extents_* is empty,
- [(2.2)](#leftpad.obs-2.2)
otherwise, *this(((*extents_*(P_rank) - index_type(1))...)) + 1[.](#leftpad.obs-2.sentence-1)
[🔗](#leftpad.obs-itemdecl:3)
`template<class... Indices>
constexpr size_t operator()(Indices... idxs) const noexcept;
`
[3](#leftpad.obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23468)
*Constraints*:
- [(3.1)](#leftpad.obs-3.1)
sizeof...(Indices) == *rank_* is true[.](#leftpad.obs-3.1.sentence-1)
- [(3.2)](#leftpad.obs-3.2)
(is_convertible_v<Indices, index_type> && ...) is true[.](#leftpad.obs-3.2.sentence-1)
- [(3.3)](#leftpad.obs-3.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) is true[.](#leftpad.obs-3.3.sentence-1)
[4](#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"))[.](#leftpad.obs-4.sentence-1)
[5](#leftpad.obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23484)
*Returns*: ((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)[.](#leftpad.obs-5.sentence-1)
[🔗](#leftpad.obs-itemdecl:4)
`static constexpr bool is_always_exhaustive() noexcept;
`
[6](#leftpad.obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23494)
*Returns*:
- [(6.1)](#leftpad.obs-6.1)
If *rank_* equals zero or one, then true;
- [(6.2)](#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)](#leftpad.obs-6.3)
otherwise, false[.](#leftpad.obs-6.sentence-1)
[🔗](#leftpad.obs-itemdecl:5)
`constexpr bool is_exhaustive() const noexcept;
`
[7](#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)[.](#leftpad.obs-7.sentence-1)
[🔗](#leftpad.obs-itemdecl:6)
`constexpr index_type stride(rank_type r) const noexcept;
`
[8](#leftpad.obs-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23525)
*Preconditions*: r is smaller than *rank_*[.](#leftpad.obs-8.sentence-1)
[9](#leftpad.obs-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23529)
*Returns*:
- [(9.1)](#leftpad.obs-9.1)
If r equals zero: 1;
- [(9.2)](#leftpad.obs-9.2)
otherwise, if r equals one: *stride-1*;
- [(9.3)](#leftpad.obs-9.3)
otherwise, the product of *stride-1* and
all values extents_.extent(k) with k in the range [1, r)[.](#leftpad.obs-9.sentence-1)
[🔗](#leftpad.obs-itemdecl:7)
`template<class LayoutLeftPaddedMapping>
friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;
`
[10](#leftpad.obs-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23548)
*Constraints*:
- [(10.1)](#leftpad.obs-10.1)
*is-layout-left-padded-mapping-of*<LayoutLeftPaddedMapping> is true[.](#leftpad.obs-10.1.sentence-1)
- [(10.2)](#leftpad.obs-10.2)
LayoutLeftPaddedMapping::extents_type::rank() == rank_ is true[.](#leftpad.obs-10.2.sentence-1)
[11](#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[.](#leftpad.obs-11.sentence-1)
Otherwise, false[.](#leftpad.obs-11.sentence-2)
#### [23.7.3.4.9](#rightpad) Class template layout_right_padded::mapping [[mdspan.layout.rightpad]](mdspan.layout.rightpad)
#### [23.7.3.4.9.1](#rightpad.overview) Overview [[mdspan.layout.rightpad.overview]](mdspan.layout.rightpad.overview)
[1](#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)[.](#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]](#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]](#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]](#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]](#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](#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[.](#rightpad.overview-2.sentence-1)
[3](#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[.](#rightpad.overview-3.sentence-1)
[4](#rightpad.overview-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23669)
Throughout [[mdspan.layout.rightpad]](#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)](#rightpad.overview-4.1)
the empty parameter pack, if *rank_* equals zero;
- [(4.2)](#rightpad.overview-4.2)
otherwise, 0zu, if *rank_* equals one;
- [(4.3)](#rightpad.overview-4.3)
otherwise, the parameter pack 0zu, 1zu, …, *rank_*- 1[.](#rightpad.overview-4.sentence-1)
[5](#rightpad.overview-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23682)
*Mandates*:
- [(5.1)](#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[.](#rightpad.overview-5.1.sentence-1)
- [(5.2)](#rightpad.overview-5.2)
padding_value is representable as a value of type index_type[.](#rightpad.overview-5.2.sentence-1)
- [(5.3)](#rightpad.overview-5.3)
If
* [(5.3.1)](#rightpad.overview-5.3.1)
*rank_* is greater than one,
* [(5.3.2)](#rightpad.overview-5.3.2)
padding_value does not equal dynamic_extent, and
* [(5.3.3)](#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[.](#rightpad.overview-5.3.sentence-1)
- [(5.4)](#rightpad.overview-5.4)
If
* [(5.4.1)](#rightpad.overview-5.4.1)
*rank_* is greater than one,
* [(5.4.2)](#rightpad.overview-5.4.2)
padding_value does not equal dynamic_extent, and
* [(5.4.3)](#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[.](#rightpad.overview-5.4.sentence-1)
#### [23.7.3.4.9.2](#rightpad.expo) Exposition-only members [[mdspan.layout.rightpad.expo]](mdspan.layout.rightpad.expo)
[🔗](#rightpad.expo-itemdecl:1)
`static constexpr size_t static-padding-stride = see below;
`
[1](#rightpad.expo-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23730)
The value is
- [(1.1)](#rightpad.expo-1.1)
0, if *rank_* equals zero or one;
- [(1.2)](#rightpad.expo-1.2)
otherwise, dynamic_extent,
if padding_value or *last-static-extent* equalsdynamic_extent;
- [(1.3)](#rightpad.expo-1.3)
otherwise, the size_t value which is*LEAST-MULTIPLE-AT-LEAST*(padding_value, *last-static-extent*)[.](#rightpad.expo-1.sentence-1)
[🔗](#rightpad.expo-itemdecl:2)
`index_type stride-rm2 = static-padding-stride;
`
[2](#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[.](#rightpad.expo-2.sentence-1)
[*Note [1](#rightpad.expo-note-1)*:
Using extents<index_type, *static-padding-stride*> instead of index_type as the type of *stride-rm2* would achieve this[.](#rightpad.expo-2.sentence-2)
— *end note*]
#### [23.7.3.4.9.3](#rightpad.cons) Constructors [[mdspan.layout.rightpad.cons]](mdspan.layout.rightpad.cons)
[🔗](#lib:layout_right_padded::mapping,constructor)
`constexpr mapping(const extents_type& ext);
`
[1](#rightpad.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23769)
*Preconditions*:
- [(1.1)](#rightpad.cons-1.1)
The size of the multidimensional index space ext is representable as a value of type index_type[.](#rightpad.cons-1.1.sentence-1)
- [(1.2)](#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*[.](#rightpad.cons-1.2.sentence-1)
- [(1.3)](#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[.](#rightpad.cons-1.3.sentence-1)
[2](#rightpad.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23790)
*Effects*:
- [(2.1)](#rightpad.cons-2.1)
Direct-non-list-initializes *extents_* with ext; and
- [(2.2)](#rightpad.cons-2.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-rm2*
* [(2.2.1)](#rightpad.cons-2.2.1)
with ext.extent(*rank_* - 1) if padding_value is dynamic_extent,
* [(2.2.2)](#rightpad.cons-2.2.2)
otherwise with*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(*rank_* - 1))[.](#rightpad.cons-2.sentence-1)
[🔗](#lib:layout_right_padded::mapping,constructor_)
`template<class OtherIndexType>
constexpr mapping(const extents_type& ext, OtherIndexType pad);
`
[3](#rightpad.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23816)
*Constraints*:
- [(3.1)](#rightpad.cons-3.1)
is_convertible_v<OtherIndexType, index_type> is true[.](#rightpad.cons-3.1.sentence-1)
- [(3.2)](#rightpad.cons-3.2)
is_nothrow_constructible_v<index_type, OtherIndexType> is true[.](#rightpad.cons-3.2.sentence-1)
[4](#rightpad.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23825)
*Preconditions*:
- [(4.1)](#rightpad.cons-4.1)
pad is representable as a value of type index_type[.](#rightpad.cons-4.1.sentence-1)
- [(4.2)](#rightpad.cons-4.2)
extents_type::*index-cast*(pad) is greater than zero[.](#rightpad.cons-4.2.sentence-1)
- [(4.3)](#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[.](#rightpad.cons-4.3.sentence-1)
- [(4.4)](#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[.](#rightpad.cons-4.4.sentence-1)
- [(4.5)](#rightpad.cons-4.5)
If padding_value is not equal to dynamic_extent,padding_value equals extents_type::*index-cast*(pad)[.](#rightpad.cons-4.5.sentence-1)
[5](#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))[.](#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](#rightpad.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23864)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#rightpad.cons-6.sentence-1)
[7](#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[.](#rightpad.cons-7.sentence-1)
[8](#rightpad.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23878)
*Preconditions*:
- [(8.1)](#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)](#rightpad.cons-8.2)
other.required_span_size() is representable as
a value of type index_type[.](#rightpad.cons-8.sentence-1)
[9](#rightpad.cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23895)
*Effects*: Equivalent to mapping(other.extents())[.](#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](#rightpad.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23908)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#rightpad.cons-10.sentence-1)
[11](#rightpad.cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23912)
*Preconditions*:
- [(11.1)](#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)](#rightpad.cons-11.2)
If *rank_* is greater than 0,
then other.stride(*rank_* - 1) equals 1[.](#rightpad.cons-11.2.sentence-1)
- [(11.3)](#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)](#rightpad.cons-11.4)
other.required_span_size() is representable as
a value of type index_type[.](#rightpad.cons-11.4.sentence-1)
[12](#rightpad.cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23939)
*Effects*:
- [(12.1)](#rightpad.cons-12.1)
Direct-non-list-initializes *extents_* with other.extents(); and
- [(12.2)](#rightpad.cons-12.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-rm2* with other.stride(*rank_* - 2)[.](#rightpad.cons-12.sentence-1)
[🔗](#lib:layout_right_padded::mapping,constructor____)
`template<class LayoutRightPaddedMapping>
constexpr explicit(see below)
mapping(const LayoutRightPaddedMapping& other);
`
[13](#rightpad.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23959)
*Constraints*:
- [(13.1)](#rightpad.cons-13.1)
*is-layout-right-padded-mapping-of*<LayoutRightPaddedMapping> is true[.](#rightpad.cons-13.1.sentence-1)
- [(13.2)](#rightpad.cons-13.2)
is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type> is true[.](#rightpad.cons-13.2.sentence-1)
[14](#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[.](#rightpad.cons-14.sentence-1)
[15](#rightpad.cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23980)
*Preconditions*:
- [(15.1)](#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)](#rightpad.cons-15.2)
other.required_span_size() is representable as
a value of type index_type[.](#rightpad.cons-15.sentence-1)
[16](#rightpad.cons-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23996)
*Effects*:
- [(16.1)](#rightpad.cons-16.1)
Direct-non-list-initializes *extents_* with other.extents(); and
- [(16.2)](#rightpad.cons-16.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-rm2* with other.stride(rank_ - 2)[.](#rightpad.cons-16.sentence-1)
[17](#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](#rightpad.cons-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24025)
*Constraints*:
- [(18.1)](#rightpad.cons-18.1)
*is-layout-left-padded-mapping-of*<LayoutLeftPaddedMapping> is true or
*is-mapping-of*<layout_left, LayoutLeftPaddedMapping> is true[.](#rightpad.cons-18.1.sentence-1)
- [(18.2)](#rightpad.cons-18.2)
*rank_* equals zero or one[.](#rightpad.cons-18.2.sentence-1)
- [(18.3)](#rightpad.cons-18.3)
is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>
is true[.](#rightpad.cons-18.3.sentence-1)
[19](#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[.](#rightpad.cons-19.sentence-1)
[20](#rightpad.cons-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24045)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#rightpad.cons-20.sentence-1)
[21](#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](#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[.](#rightpad.cons-21.sentence-1)
— *end note*]
#### [23.7.3.4.9.4](#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](#rightpad.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24070)
*Returns*: array<index_type, *rank_*>(stride(P_rank)...)[.](#rightpad.obs-1.sentence-1)
[🔗](#lib:layout_right_padded::mapping,required_span_size)
`constexpr index_type required_span_size() const noexcept;
`
[2](#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[.](#rightpad.obs-2.sentence-1)
[🔗](#lib:layout_right_padded::mapping,operator())
`template<class... Indices>
constexpr size_t operator()(Indices... idxs) const noexcept;
`
[3](#rightpad.obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24094)
*Constraints*:
- [(3.1)](#rightpad.obs-3.1)
sizeof...(Indices) == *rank_* is true[.](#rightpad.obs-3.1.sentence-1)
- [(3.2)](#rightpad.obs-3.2)
(is_convertible_v<Indices, index_type> && ...) is true[.](#rightpad.obs-3.2.sentence-1)
- [(3.3)](#rightpad.obs-3.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) is true[.](#rightpad.obs-3.3.sentence-1)
[4](#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"))[.](#rightpad.obs-4.sentence-1)
[5](#rightpad.obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24110)
*Returns*: ((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)[.](#rightpad.obs-5.sentence-1)
[🔗](#lib:layout_right_padded::mapping,is_always_exhaustive)
`static constexpr bool is_always_exhaustive() noexcept;
`
[6](#rightpad.obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24121)
*Returns*:
- [(6.1)](#rightpad.obs-6.1)
If *rank_* equals zero or one, then true;
- [(6.2)](#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)](#rightpad.obs-6.3)
otherwise, false[.](#rightpad.obs-6.sentence-1)
[🔗](#lib:layout_right_padded::mapping,is_exhaustive)
`constexpr bool is_exhaustive() const noexcept;
`
[7](#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)
[🔗](#rightpad.obs-itemdecl:6)
`constexpr index_type stride(rank_type r) const noexcept;
`
[8](#rightpad.obs-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24156)
*Preconditions*: r is smaller than *rank_*[.](#rightpad.obs-8.sentence-1)
[9](#rightpad.obs-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24160)
*Returns*:
- [(9.1)](#rightpad.obs-9.1)
If r equals *rank_* - 1: 1;
- [(9.2)](#rightpad.obs-9.2)
otherwise, if r equals *rank_* - 2: *stride-rm2*;
- [(9.3)](#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)[.](#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](#rightpad.obs-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24182)
*Constraints*:
- [(10.1)](#rightpad.obs-10.1)
*is-layout-right-padded-mapping-of*<LayoutRightPaddedMapping> is true[.](#rightpad.obs-10.1.sentence-1)
- [(10.2)](#rightpad.obs-10.2)
LayoutRightPaddedMapping::extents_type::rank() == *rank_* is true[.](#rightpad.obs-10.2.sentence-1)
[11](#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[.](#rightpad.obs-11.sentence-1)
Otherwise, false[.](#rightpad.obs-11.sentence-2)