[mdspan.layout.stride]

# 23 Containers library [[containers]](./#containers)

## 23.7 Views [[views]](views#mdspan.layout.stride)

### 23.7.3 Multidimensional access [[views.multidim]](views.multidim#mdspan.layout.stride)

#### 23.7.3.4 Layout mapping [[mdspan.layout]](mdspan.layout#stride)

#### 23.7.3.4.7 Class template layout_stride​::​mapping [mdspan.layout.stride]

#### [23.7.3.4.7.1](#overview) Overview [[mdspan.layout.stride.overview]](mdspan.layout.stride.overview)

[1](#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[.](#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]](#cons "23.7.3.4.7.3 Constructors"), 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]](#obs "23.7.3.4.7.4 Observers"), 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.6 Specializations 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#L22636)

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#L22640)

layout_stride​::​mapping<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") for each E[.](#overview-3.sentence-1)

[4](#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[.](#overview-4.sentence-1)

#### [23.7.3.4.7.2](#expo) Exposition-only helpers [[mdspan.layout.stride.expo]](mdspan.layout.stride.expo)

[1](#expo-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22652)

Let *REQUIRED-SPAN-SIZE*(e, strides) be:

- [(1.1)](#expo-1.1)

1, if e.rank() == 0 is true,

- [(1.2)](#expo-1.2)

otherwise 0, if the size of the multidimensional index space e is 0,

- [(1.3)](#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())[.](#expo-1.sentence-1)

[2](#expo-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22668)

Let *OFFSET*(m) be:

- [(2.1)](#expo-2.1)

m(), if e.rank() == 0 is true,

- [(2.2)](#expo-2.2)

otherwise 0, if the size of the multidimensional index space e is 0,

- [(2.3)](#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[.](#expo-2.sentence-1)

[3](#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](#expo-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22691)

Let [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]") be the exposition-only concept
defined as follows:template<class M>concept [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]") = requires { // *exposition only*requires *is-extents*<typename M::extents_type>; { M::is_always_strided() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<bool>; { M::is_always_exhaustive() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<bool>; { M::is_always_unique() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept 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](#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[.](#expo-4.sentence-1)

â *end note*]

#### [23.7.3.4.7.3](#cons) Constructors [[mdspan.layout.stride.cons]](mdspan.layout.stride.cons)

[ð](#lib:layout_stride::mapping,constructor)

`constexpr mapping() noexcept;
`

[1](#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.2 Fundamental types"))[.](#cons-1.sentence-1)

[2](#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)[.](#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](#cons-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22745)

*Constraints*: 

- [(3.1)](#cons-3.1)

is_convertible_v<const OtherIndexType&, index_type> is true, and

- [(3.2)](#cons-3.2)

is_nothrow_constructible_v<index_type, const OtherIndexType&> is true[.](#cons-3.sentence-1)

[4](#cons-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22754)

*Preconditions*: 

- [(4.1)](#cons-4.1)

  The result of converting s[i] to index_type is greater than 0 for all i in the range [0, *rank_*)[.](#cons-4.1.sentence-1)

- [(4.2)](#cons-4.2)

  *REQUIRED-SPAN-SIZE*(e, s) is representable
as a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#cons-4.2.sentence-1)

- [(4.3)](#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[.](#cons-4.3.sentence-1)
  [*Note [1](#cons-note-1)*:
  For layout_stride,
this condition is necessary and sufficient
for is_unique() to be true[.](#cons-4.3.sentence-2)
 â *end note*]

[5](#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])[.](#cons-5.sentence-1)

[ð](#lib:layout_stride::mapping,constructor__)

`template<class StridedLayoutMapping>
  constexpr explicit(see below)
    mapping(const StridedLayoutMapping& other) noexcept;
`

[6](#cons-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22793)

*Constraints*: 

- [(6.1)](#cons-6.1)

  [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]")<StridedLayoutMapping> is satisfied[.](#cons-6.1.sentence-1)

- [(6.2)](#cons-6.2)

  is_constructible_v<extents_type, typename StridedLayoutMapping​::​extents_type> is  
  true[.](#cons-6.2.sentence-2)

- [(6.3)](#cons-6.3)

  StridedLayoutMapping​::​is_always_unique() is true[.](#cons-6.3.sentence-1)

- [(6.4)](#cons-6.4)

  StridedLayoutMapping​::​is_always_strided() is true[.](#cons-6.4.sentence-1)

[7](#cons-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22806)

*Preconditions*: 

- [(7.1)](#cons-7.1)

StridedLayoutMapping meets the layout mapping requirements ([[mdspan.layout.reqmts]](mdspan.layout.reqmts "23.7.3.4.2 Requirements")),

- [(7.2)](#cons-7.2)

other.stride(r) > 0 is true for every rank index r of extents(),

- [(7.3)](#cons-7.3)

other.required_span_size() is representable as
a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")), and

- [(7.4)](#cons-7.4)

*OFFSET*(other) == 0 is true[.](#cons-7.sentence-1)

[8](#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)[.](#cons-8.sentence-1)

[9](#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](#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](#obs-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22848)

*Returns*: *REQUIRED-SPAN-SIZE*(extents(), *strides_*)[.](#obs-1.sentence-1)

[ð](#lib:operator(),layout_stride::mapping)

`template<class... Indices>
  constexpr index_type operator()(Indices... i) const noexcept;
`

[2](#obs-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22860)

*Constraints*: 

- [(2.1)](#obs-2.1)

sizeof...(Indices) == *rank_* is true,

- [(2.2)](#obs-2.2)

(is_convertible_v<Indices, index_type> && ...) is true, and

- [(2.3)](#obs-2.3)

(is_nothrow_constructible_v<index_type, Indices> && ...) is true[.](#obs-2.sentence-1)

[3](#obs-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22871)

*Preconditions*: extents_type​::​*index-cast*(i) is
a multidimensional index in *extents_* ([[mdspan.overview]](mdspan.overview "23.7.3.1 Overview"))[.](#obs-3.sentence-1)

[4](#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[.](#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](#obs-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22895)

*Returns*: 

- [(5.1)](#obs-5.1)

  true if *rank_* is 0[.](#obs-5.1.sentence-1)

- [(5.2)](#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[.](#obs-5.2.sentence-1)

- [(5.3)](#obs-5.3)

  Otherwise, false[.](#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](#obs-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22919)

*Constraints*: 

- [(6.1)](#obs-6.1)

  [*layout-mapping-alike*](#concept:layout-mapping-alike "23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]")<OtherMapping> is satisfied[.](#obs-6.1.sentence-1)

- [(6.2)](#obs-6.2)

  *rank_* == OtherMapping​::​extents_type​::​rank() is true[.](#obs-6.2.sentence-1)

- [(6.3)](#obs-6.3)

  OtherMapping​::​is_always_strided() is true[.](#obs-6.3.sentence-1)

[7](#obs-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L22930)

*Preconditions*: OtherMapping meets the layout mapping requirements ([[mdspan.layout.policy.reqmts]](mdspan.layout.policy.reqmts "23.7.3.4.3 Layout mapping policy requirements"))[.](#obs-7.sentence-1)

[8](#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())[.](#obs-8.sentence-1)

Otherwise, false[.](#obs-8.sentence-2)
