[mdspan.sub.map]

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

## 23.7 Views [[views]](views#mdspan.sub.map)

### 23.7.3 Multidimensional access [[views.multidim]](views.multidim#mdspan.sub.map)

#### 23.7.3.7 submdspan [[mdspan.sub]](mdspan.sub#map)

#### 23.7.3.7.6 Specializations of submdspan_mapping [mdspan.sub.map]

#### [23.7.3.7.6.1](#common) Common [[mdspan.sub.map.common]](mdspan.sub.map.common)

[1](#common-1)

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

The following elements apply to all functions in [mdspan.sub.map][.](#common-1.sentence-1)

[2](#common-2)

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

*Constraints*: sizeof...(slices) equals extents_type​::​rank()[.](#common-2.sentence-1)

[3](#common-3)

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

*Mandates*: For each rank index k of extents(),
exactly one of the following is true:

- [(3.1)](#common-3.1)

Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<index_type>,

- [(3.2)](#common-3.2)

Sk models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<index_type>,

- [(3.3)](#common-3.3)

is_convertible_v<Sk, full_extent_t> is true, or

- [(3.4)](#common-3.4)

Sk is a specialization of strided_slice[.](#common-3.sentence-1)

[4](#common-4)

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

*Preconditions*: For each rank index k of extents(),
all of the following are true:

- [(4.1)](#common-4.1)

if Sk is a specialization of strided_slice,sk.extent is equal to zero orsk.stride is greater than zero; and

- [(4.2)](#common-4.2)

0 â¤ *first_*<index_type, k>(slices...)   
0  â¤ *last_*<k>(extents(), slices...)   
0  â¤ extents().extent(k)

[5](#common-5)

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

Let sub_ext be
the result of submdspan_extents(extents(), slices...) and
let SubExtents be decltype(sub_ext)[.](#common-5.sentence-1)

[6](#common-6)

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

Let sub_strides be
an array<SubExtents​::​index_type, SubExtents​::​rank()> such that for each rank index k of extents() for which *map-rank*[k] is not dynamic_extent,sub_strides[*map-rank*[k]] equals:

- [(6.1)](#common-6.1)

stride(k) * *de-ice*(sk.stride) if Sk is a specialization of strided_slice andsk.stride < sk.extent is true;

- [(6.2)](#common-6.2)

otherwise, stride(k)[.](#common-6.sentence-1)

[7](#common-7)

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

Let P be a parameter pack
such that is_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true[.](#common-7.sentence-1)

[8](#common-8)

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

If *first_*<index_type, k>(slices...) equals extents().extent(k) for any rank index k of extents(), then
let offset be a value of type size_t equal to(*this).required_span_size()[.](#common-8.sentence-1)

Otherwise,
let offset be a value of type size_t equal to(*this)(*first_*<index_type, P>(slices...)...)[.](#common-8.sentence-2)

[9](#common-9)

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

Given a layout mapping type M, a type S is a[*unit-stride slice for M*](#def:slice,unit-stride "23.7.3.7.6.1 Common [mdspan.sub.map.common]") if

- [(9.1)](#common-9.1)

S is a specialization of strided_slice where S​::​stride_type models [*integral-constant-like*](span.syn#concept:integral-constant-like "23.7.2.1 Header <span> synopsis [span.syn]") and S​::​stride_type​::​value equals 1,

- [(9.2)](#common-9.2)

S models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<M​::​index_type>, or

- [(9.3)](#common-9.3)

is_convertible_v<S, full_extent_t> is true[.](#common-9.sentence-1)

#### [23.7.3.7.6.2](#left) layout_left specialization of submdspan_mapping [[mdspan.sub.map.left]](mdspan.sub.map.left)

[ð](#lib:layout_left::mapping,submdspan-mapping-impl)

`template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_left::mapping<Extents>::submdspan-mapping-impl(
      SliceSpecifiers... slices) const -> see below;
`

[1](#left-1)

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

*Returns*: 

- [(1.1)](#left-1.1)

submdspan_mapping_result{*this, 0},
if Extents​::​rank() == 0 is true;

- [(1.2)](#left-1.2)

otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset},
if SubExtents​::​rank() == 0 is true;

- [(1.3)](#left-1.3)

otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset},
if
  * [(1.3.1)](#left-1.3.1)

for each k in the range [0, SubExtents​::​rank() - 1)), is_convertible_v<Sk, full_extent_t> is true; and

  * [(1.3.2)](#left-1.3.2)

for k equal to SubExtents​::​rank() - 1, Sk is a unit-stride slice for mapping;

  [*Note [1](#left-note-1)*:
  If the above conditions are true,
all Sk with k larger than SubExtents​::​rank() - 1 are convertible to index_type[.](#left-1.3.sentence-1)
 â *end note*]

- [(1.4)](#left-1.4)

otherwise,submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)),
 offset} if for a value u for which u+1 is
the smallest value p larger than zero
for which Sp is a unit-stride slice for mapping,
the following conditions are met:
  * [(1.4.1)](#left-1.4.1)

S0 is a unit-stride slice for mapping; and

  * [(1.4.2)](#left-1.4.2)

for each k in the range [u + 1, u + SubExtents​::​rank() - 1),is_convertible_v<Sk, full_extent_t> is true; and

  * [(1.4.3)](#left-1.4.3)

for k equal to u + SubExtents​::​rank() - 1,Sk is a unit-stride slice for mapping;

and where S_static is:
  * [(1.4.4)](#left-1.4.4)

dynamic_extent,
if static_extent(k) is dynamic_extent for any k in the range [0, u + 1),

  * [(1.4.5)](#left-1.4.5)

otherwise, the product of all valuesstatic_extent(k) for k in the range [0, u + 1);

- [(1.5)](#left-1.5)

otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

#### [23.7.3.7.6.3](#right) layout_right specialization of submdspan_mapping [[mdspan.sub.map.right]](mdspan.sub.map.right)

[ð](#lib:layout_right::mapping,submdspan-mapping-impl)

`template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_right::mapping<Extents>::submdspan-mapping-impl(
      SliceSpecifiers... slices) const -> see below;
`

[1](#right-1)

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

*Returns*: 

- [(1.1)](#right-1.1)

submdspan_mapping_result{*this, 0},
if Extents​::​rank() == 0 is true;

- [(1.2)](#right-1.2)

otherwise,submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset},
if SubExtents​::​rank() == 0 is true;

- [(1.3)](#right-1.3)

otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset},
if
  * [(1.3.1)](#right-1.3.1)

for each k in the range [*rank_* - SubExtents​::​rank() + 1, *rank_*), is_convertible_v<Sk, full_extent_t> is true; and

  * [(1.3.2)](#right-1.3.2)

for k equal to *_rank* - SubExtents​::​rank(), Sk is a unit-stride slice for mapping;

  [*Note [1](#right-note-1)*:
  If the above conditions are true,
all Sk with k<_rankÂ - SubExtents::rank() are convertible to index_type[.](#right-1.3.sentence-1)
 â *end note*]

- [(1.4)](#right-1.4)

otherwise,submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
 stride(*rank_* - u - 2)), offset} if for a value u for which rank_âuâ2 is
the largest value p smaller than *rank_* - 1 for which Sp is a unit-stride slice for mapping,
the following conditions are met:
  * [(1.4.1)](#right-1.4.1)

for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping; and

  * [(1.4.2)](#right-1.4.2)

for each k in the range
[*rank_* - SubExtents​::​rank() - u + 1, *rank_* - u - 1),is_convertible_v<Sk, full_extent_t> is true; and

  * [(1.4.3)](#right-1.4.3)

for k equal to *rank_* - SubExtents​::​rank() - u,  
Sk is a unit-stride slice for mapping;

and where S_static is:
  * [(1.4.4)](#right-1.4.4)

dynamic_extent,
if static_extent(k) is dynamic_extent for any k in the range [*rank_* - u - 1, *rank_*),

  * [(1.4.5)](#right-1.4.5)

otherwise, the product of all valuesstatic_extent(k) for k in the range [*rank_* - u - 1, *rank_*);

- [(1.5)](#right-1.5)

otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

#### [23.7.3.7.6.4](#stride) layout_stride specialization of submdspan_mapping [[mdspan.sub.map.stride]](mdspan.sub.map.stride)

[ð](#lib:layout_stride::mapping,submdspan-mapping-impl)

`template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_stride::mapping<Extents>::submdspan-mapping-impl(
      SliceSpecifiers... slices) const -> see below;
`

[1](#stride-1)

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

*Returns*: 

- [(1.1)](#stride-1.1)

submdspan_mapping_result{*this, 0},
if Extents​::​rank() == 0 is true;

- [(1.2)](#stride-1.2)

otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

#### [23.7.3.7.6.5](#leftpad) layout_left_padded specialization of submdspan_mapping [[mdspan.sub.map.leftpad]](mdspan.sub.map.leftpad)

[ð](#lib:layout_left_padded::mapping,submdspan-mapping-impl)

`template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_left_padded::mapping<Extents>::submdspan-mapping-impl(
    SliceSpecifiers... slices) const -> see below;
`

[1](#leftpad-1)

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

*Returns*: 

- [(1.1)](#leftpad-1.1)

submdspan_mapping_result{*this, 0},
if Extents​::​rank() == 0 is true;

- [(1.2)](#leftpad-1.2)

otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset},
if *rank_* == 1 is true orSubExtents​::​rank() == 0 is true;

- [(1.3)](#leftpad-1.3)

otherwise,submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset},
if
  * [(1.3.1)](#leftpad-1.3.1)

SubExtents​::​rank() == 1 is true and

  * [(1.3.2)](#leftpad-1.3.2)

S0 is a unit-stride slice for mapping;

- [(1.4)](#leftpad-1.4)

otherwise,submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)),
 offset} if for a value u for which u + 1 is the smallest value p larger than zero
for which Sp is a unit-stride slice for mapping,
the following conditions are met:
  * [(1.4.1)](#leftpad-1.4.1)

S0 is a unit-stride slice for mapping; and

  * [(1.4.2)](#leftpad-1.4.2)

for each k in the range [u + 1, u + SubExtents​::​rank() - 1),is_convertible_v<Sk, full_extent_t> is true; and

  * [(1.4.3)](#leftpad-1.4.3)

for k equal to u + SubExtents​::​rank() - 1,Sk is a unit-stride slice for mapping;

where S_static is:
  * [(1.4.4)](#leftpad-1.4.4)

dynamic_extent,
if *static-padding-stride* is dynamic_extent orstatic_extent(k) is dynamic_extent for any k in the range [1, u + 1),

  * [(1.4.5)](#leftpad-1.4.5)

otherwise, the product of *static-padding-stride* and
all values static_extent(k) for k in the range [1, u + 1);

- [(1.5)](#leftpad-1.5)

otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

#### [23.7.3.7.6.6](#rightpad) layout_right_padded specialization of submdspan_mapping [[mdspan.sub.map.rightpad]](mdspan.sub.map.rightpad)

[ð](#lib:layout_right_padded::mapping,submdspan-mapping-impl)

`template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_right_padded::mapping<Extents>::submdspan-mapping-impl(
    SliceSpecifiers... slices) const -> see below;
`

[1](#rightpad-1)

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

*Returns*: 

- [(1.1)](#rightpad-1.1)

submdspan_mapping_result{*this, 0},
if *rank_* == 0 is true;

- [(1.2)](#rightpad-1.2)

otherwise,submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset},  
if *rank_* == 1 is true orSubExtents​::​rank() == 0 is true;

- [(1.3)](#rightpad-1.3)

otherwise,submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset},
if
  * [(1.3.1)](#rightpad-1.3.1)

SubExtents​::​rank() == 1 is true and

  * [(1.3.2)](#rightpad-1.3.2)

for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping;

- [(1.4)](#rightpad-1.4)

otherwise,submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
 stride(*rank_* - u - 2)), offset} if for a value u for which *rank_* - u - 2 is the largest value p smaller than *rank_* - 1 for which Sp is a unit-stride slice for mapping,
the following conditions are met:
  * [(1.4.1)](#rightpad-1.4.1)

for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping; and

  * [(1.4.2)](#rightpad-1.4.2)

for each k in the range
[*rank_* - SubExtents​::​rank() - u + 1, *rank_* - u - 1)),is_convertible_v<Sk, full_extent_t> is true; and

  * [(1.4.3)](#rightpad-1.4.3)

for k equal to *rank_* - SubExtents​::​rank() - u,  
Sk is a unit-stride slice for mapping;

and where S_static is:
  * [(1.4.4)](#rightpad-1.4.4)

dynamic_extent if *static-padding-stride* is dynamic_extent or
for any k in the range [*rank_* - u - 1, *rank_* - 1)static_extent(k) is dynamic_extent,

  * [(1.4.5)](#rightpad-1.4.5)

otherwise, the product of *static-padding-stride* and
all values static_extent(k) with k in the range [*rank_* - u - 1, *rank_* - 1);

- [(1.5)](#rightpad-1.5)

otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
