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

649 lines
22 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.leftpad]
# 23 Containers library [[containers]](./#containers)
## 23.7 Views [[views]](views#mdspan.layout.leftpad)
### 23.7.3 Multidimensional access [[views.multidim]](views.multidim#mdspan.layout.leftpad)
#### 23.7.3.4 Layout mapping [[mdspan.layout]](mdspan.layout#leftpad)
#### 23.7.3.4.8 Class template layout_left_padded::mapping [mdspan.layout.leftpad]
#### [23.7.3.4.8.1](#overview) Overview [[mdspan.layout.leftpad.overview]](mdspan.layout.leftpad.overview)
[1](#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)[.](#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]](#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]](#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]](#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]](#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](#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[.](#overview-2.sentence-1)
[3](#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[.](#overview-3.sentence-1)
[4](#overview-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23043)
Throughout [mdspan.layout.leftpad],
let P_rank be the following
size *rank_* parameter pack of size_t values:
- [(4.1)](#overview-4.1)
the empty parameter pack, if *rank_* equals zero;
- [(4.2)](#overview-4.2)
otherwise, 0zu, if *rank_* equals one;
- [(4.3)](#overview-4.3)
otherwise, the parameter pack 0zu, 1zu, …, *rank_*- 1[.](#overview-4.sentence-1)
[5](#overview-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23056)
*Mandates*:
- [(5.1)](#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[.](#overview-5.1.sentence-1)
- [(5.2)](#overview-5.2)
padding_value is representable as a value of type index_type[.](#overview-5.2.sentence-1)
- [(5.3)](#overview-5.3)
If
* [(5.3.1)](#overview-5.3.1)
*rank_* is greater than one,
* [(5.3.2)](#overview-5.3.2)
padding_value does not equal dynamic_extent, and
* [(5.3.3)](#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[.](#overview-5.3.sentence-1)
- [(5.4)](#overview-5.4)
If
* [(5.4.1)](#overview-5.4.1)
*rank_* is greater than one,
* [(5.4.2)](#overview-5.4.2)
padding_value does not equal dynamic_extent, and
* [(5.4.3)](#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[.](#overview-5.4.sentence-1)
#### [23.7.3.4.8.2](#expo) Exposition-only members [[mdspan.layout.leftpad.expo]](mdspan.layout.leftpad.expo)
[🔗](#expo-itemdecl:1)
`static constexpr size_t static-padding-stride = see below;
`
[1](#expo-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23104)
The value is
- [(1.1)](#expo-1.1)
0, if *rank_* equals zero or one;
- [(1.2)](#expo-1.2)
otherwise, dynamic_extent,
if padding_value or *first-static-extent* equalsdynamic_extent;
- [(1.3)](#expo-1.3)
otherwise, the size_t value which is*LEAST-MULTIPLE-AT-LEAST*(padding_value, *first-static-extent*)[.](#expo-1.sentence-1)
[🔗](#expo-itemdecl:2)
`index_type stride-1 = static-padding-stride;
`
[2](#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[.](#expo-2.sentence-1)
[*Note [1](#expo-note-1)*:
Using extents<index_type, *static-padding-stride*> instead ofindex_type as the type of *stride-1* would achieve this[.](#expo-2.sentence-2)
— *end note*]
#### [23.7.3.4.8.3](#cons) Constructors [[mdspan.layout.leftpad.cons]](mdspan.layout.leftpad.cons)
[🔗](#lib:layout_left_padded::mapping,constructor)
`constexpr mapping(const extents_type& ext);
`
[1](#cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23142)
*Preconditions*:
- [(1.1)](#cons-1.1)
The size of the multidimensional index space ext is representable as
a value of type index_type[.](#cons-1.1.sentence-1)
- [(1.2)](#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*[.](#cons-1.2.sentence-1)
- [(1.3)](#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[.](#cons-1.3.sentence-1)
[2](#cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23163)
*Effects*:
- [(2.1)](#cons-2.1)
Direct-non-list-initializes *extents_* with ext; and
- [(2.2)](#cons-2.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-1*
* [(2.2.1)](#cons-2.2.1)
with ext.extent(0) if padding_value is dynamic_extent,
* [(2.2.2)](#cons-2.2.2)
otherwise with*LEAST-MULTIPLE-AT-LEAST*(padding_value, ext.extent(0))[.](#cons-2.sentence-1)
[🔗](#lib:layout_left_padded::mapping,constructor_)
`template<class OtherIndexType>
constexpr mapping(const extents_type& ext, OtherIndexType pad);
`
[3](#cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23188)
*Constraints*:
- [(3.1)](#cons-3.1)
is_convertible_v<OtherIndexType, index_type> is true[.](#cons-3.1.sentence-1)
- [(3.2)](#cons-3.2)
is_nothrow_constructible_v<index_type, OtherIndexType> is true[.](#cons-3.2.sentence-1)
[4](#cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23197)
*Preconditions*:
- [(4.1)](#cons-4.1)
pad is representable as a value of type index_type[.](#cons-4.1.sentence-1)
- [(4.2)](#cons-4.2)
extents_type::index-cast(pad) is greater than zero[.](#cons-4.2.sentence-1)
- [(4.3)](#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)](#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[.](#cons-4.4.sentence-1)
- [(4.5)](#cons-4.5)
If padding_value is not equal to dynamic_extent,padding_value equals extents_type::*index-cast*(pad)[.](#cons-4.5.sentence-1)
[5](#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))[.](#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](#cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23236)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#cons-6.sentence-1)
[7](#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[.](#cons-7.sentence-1)
[8](#cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23250)
*Preconditions*:
- [(8.1)](#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)](#cons-8.2)
other.required_span_size() is representable as
a value of type index_type[.](#cons-8.sentence-1)
[9](#cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23267)
*Effects*: Equivalent to mapping(other.extents())[.](#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](#cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23280)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#cons-10.sentence-1)
[11](#cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23284)
*Preconditions*:
- [(11.1)](#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)](#cons-11.2)
If *rank_* is greater than 0,
then other.stride(0) equals 1[.](#cons-11.2.sentence-1)
- [(11.3)](#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)](#cons-11.4)
other.required_span_size() is representable as
a value of type *index_type*[.](#cons-11.4.sentence-1)
[12](#cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23310)
*Effects*:
- [(12.1)](#cons-12.1)
Direct-non-list-initializes *extents_* with other.extents() and
- [(12.2)](#cons-12.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-1* withother.stride(1)[.](#cons-12.sentence-1)
[🔗](#lib:layout_left_padded::mapping,constructor____)
`template<class LayoutLeftPaddedMapping>
constexpr explicit(see below)
mapping(const LayoutLeftPaddedMapping& other);
`
[13](#cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23330)
*Constraints*:
- [(13.1)](#cons-13.1)
*is-layout-left-padded-mapping-of*<LayoutLeftPaddedMapping> is true[.](#cons-13.1.sentence-1)
- [(13.2)](#cons-13.2)
is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>
is true[.](#cons-13.2.sentence-1)
[14](#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[.](#cons-14.sentence-1)
[15](#cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23352)
*Preconditions*:
- [(15.1)](#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)](#cons-15.2)
other.required_span_size() is representable as
a value of type index_type[.](#cons-15.sentence-1)
[16](#cons-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23368)
*Effects*:
- [(16.1)](#cons-16.1)
Direct-non-list-initializes *extents_* with other.extents() and
- [(16.2)](#cons-16.2)
if *rank_* is greater than one,
direct-non-list-initializes *stride-1* with other.stride(1)[.](#cons-16.sentence-1)
[17](#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](#cons-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23396)
*Constraints*:
- [(18.1)](#cons-18.1)
*is-layout-right-padded-mapping-of*<LayoutRightPaddedMapping> is true or
*is-mapping-of*<layout_right, LayoutRightPaddedMapping> is true[.](#cons-18.1.sentence-1)
- [(18.2)](#cons-18.2)
*rank_* equals zero or one[.](#cons-18.2.sentence-1)
- [(18.3)](#cons-18.3)
is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type> is true[.](#cons-18.3.sentence-1)
[19](#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[.](#cons-19.sentence-1)
[20](#cons-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23416)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#cons-20.sentence-1)
[21](#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](#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[.](#cons-21.sentence-2)
— *end note*]
#### [23.7.3.4.8.4](#obs) Observers [[mdspan.layout.leftpad.obs]](mdspan.layout.leftpad.obs)
[🔗](#obs-itemdecl:1)
`constexpr array<index_type, rank_> strides() const noexcept;
`
[1](#obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23442)
*Returns*: array<index_type, *rank_*>({stride(P_rank)...})[.](#obs-1.sentence-1)
[🔗](#obs-itemdecl:2)
`constexpr index_type required_span_size() const noexcept;
`
[2](#obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23452)
*Returns*:
- [(2.1)](#obs-2.1)
0 if the multidimensional index space *extents_* is empty,
- [(2.2)](#obs-2.2)
otherwise, *this(((*extents_*(P_rank) - index_type(1))...)) + 1[.](#obs-2.sentence-1)
[🔗](#obs-itemdecl:3)
`template<class... Indices>
constexpr size_t operator()(Indices... idxs) const noexcept;
`
[3](#obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23468)
*Constraints*:
- [(3.1)](#obs-3.1)
sizeof...(Indices) == *rank_* is true[.](#obs-3.1.sentence-1)
- [(3.2)](#obs-3.2)
(is_convertible_v<Indices, index_type> && ...) is true[.](#obs-3.2.sentence-1)
- [(3.3)](#obs-3.3)
(is_nothrow_constructible_v<index_type, Indices> && ...) is true[.](#obs-3.3.sentence-1)
[4](#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"))[.](#obs-4.sentence-1)
[5](#obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23484)
*Returns*: ((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)[.](#obs-5.sentence-1)
[🔗](#obs-itemdecl:4)
`static constexpr bool is_always_exhaustive() noexcept;
`
[6](#obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23494)
*Returns*:
- [(6.1)](#obs-6.1)
If *rank_* equals zero or one, then true;
- [(6.2)](#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)](#obs-6.3)
otherwise, false[.](#obs-6.sentence-1)
[🔗](#obs-itemdecl:5)
`constexpr bool is_exhaustive() const noexcept;
`
[7](#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)[.](#obs-7.sentence-1)
[🔗](#obs-itemdecl:6)
`constexpr index_type stride(rank_type r) const noexcept;
`
[8](#obs-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23525)
*Preconditions*: r is smaller than *rank_*[.](#obs-8.sentence-1)
[9](#obs-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23529)
*Returns*:
- [(9.1)](#obs-9.1)
If r equals zero: 1;
- [(9.2)](#obs-9.2)
otherwise, if r equals one: *stride-1*;
- [(9.3)](#obs-9.3)
otherwise, the product of *stride-1* and
all values extents_.extent(k) with k in the range [1, r)[.](#obs-9.sentence-1)
[🔗](#obs-itemdecl:7)
`template<class LayoutLeftPaddedMapping>
friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;
`
[10](#obs-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L23548)
*Constraints*:
- [(10.1)](#obs-10.1)
*is-layout-left-padded-mapping-of*<LayoutLeftPaddedMapping> is true[.](#obs-10.1.sentence-1)
- [(10.2)](#obs-10.2)
LayoutLeftPaddedMapping::extents_type::rank() == rank_ is true[.](#obs-10.2.sentence-1)
[11](#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[.](#obs-11.sentence-1)
Otherwise, false[.](#obs-11.sentence-2)