[mdspan.sub.sub]

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

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

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

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

#### 23.7.3.7.7 submdspan function template [mdspan.sub.sub]

[ð](#lib:submdspan)

`template<class ElementType, class Extents, class LayoutPolicy,
         class AccessorPolicy, class... SliceSpecifiers>
  constexpr auto submdspan(
    const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
    SliceSpecifiers... slices) -> see below;
`

[1](#1)

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

Let index_type be typename Extents​::​index_type[.](#1.sentence-1)

[2](#2)

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

Let sub_map_offset be the result ofsubmdspan_mapping(src.mapping(), slices...)[.](#2.sentence-1)

[*Note [1](#note-1)*:

This invocation of submdspan_mapping selects a function call via overload resolution
on a candidate set that includes the lookup set
found by argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup"))[.](#2.sentence-2)

â *end note*]

[3](#3)

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

*Constraints*: 

- [(3.1)](#3.1)

sizeof...(slices) equals Extents​::​rank(), and

- [(3.2)](#3.2)

the expression submdspan_mapping(src.mapping(), slices...) is well-formed when treated as an unevaluated operand[.](#3.sentence-1)

[4](#4)

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

*Mandates*: 

- [(4.1)](#4.1)

  decltype(submdspan_mapping(src.mapping(), slices...)) is a specialization of submdspan_mapping_result[.](#4.1.sentence-1)

- [(4.2)](#4.2)

  is_same_v<remove_cvref_t<decltype(sub_map_offset.mapping.extents())>,decltype(submdspan_extents(src.mapping(), slices...))> is true[.](#4.2.sentence-1)

- [(4.3)](#4.3)

  For each rank index k of src.extents(),
exactly one of the following is true:
  * [(4.3.1)](#4.3.1)

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

  * [(4.3.2)](#4.3.2)

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

  * [(4.3.3)](#4.3.3)

is_convertible_v<Sk, full_extent_t> is true, or

  * [(4.3.4)](#4.3.4)

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

[5](#5)

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

*Preconditions*: 

- [(5.1)](#5.1)

For each rank index k of src.extents(),
all of the following are true:
  * [(5.1.1)](#5.1.1)

if Sk is a specialization of strided_slice
    +
          [(5.1.1.1)](#5.1.1.1)
sk.extent=0, or

    +
          [(5.1.1.2)](#5.1.1.2)
sk.stride>0

  * [(5.1.2)](#5.1.2)

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

- [(5.2)](#5.2)

sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...) is true; and

- [(5.3)](#5.3)

for each integer pack I which is a multidimensional index
in sub_map_offset.mapping.extents(),sub_map_offset.mapping(I...) + sub_map_offset.offset == src.mapping()(*src-indices*(array{I...}, slices...)) is true[.](#5.sentence-1)

[*Note [2](#note-2)*:

These conditions ensure that the mapping returned by submdspan_mapping matches the algorithmically expected index-mapping given the slice specifiers[.](#5.sentence-2)

â *end note*]

[6](#6)

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

*Effects*: Equivalent to:auto sub_map_result = submdspan_mapping(src.mapping(), slices...);return mdspan(src.accessor().offset(src.data_handle(), sub_map_result.offset),
 sub_map_result.mapping, typename AccessorPolicy::offset_policy(src.accessor()));

[7](#7)

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

[*Example [1](#example-1)*:

Given a rank-3 mdspan grid3d representing a three-dimensional grid
of regularly spaced points in a rectangular prism,
the function zero_surface sets all elements on
the surface of the 3-dimensional shape to zero[.](#7.sentence-1)

It does so by reusing a function zero_2d that takes a rank-2 mdspan[.](#7.sentence-2)

// zero out all elements in an mdspantemplate<class T, class E, class L, class A>void zero_2d(mdspan<T, E, L, A> a) {static_assert(a.rank() == 2); for (int i = 0; i < a.extent(0); i++)for (int j = 0; j < a.extent(1); j++) a[i, j] = 0;}// zero out just the surfacetemplate<class T, class E, class L, class A>void zero_surface(mdspan<T, E, L, A> grid3d) {static_assert(grid3d.rank() == 3);
 zero_2d(submdspan(grid3d, 0, full_extent, full_extent));
 zero_2d(submdspan(grid3d, full_extent, 0, full_extent));
 zero_2d(submdspan(grid3d, full_extent, full_extent, 0));
 zero_2d(submdspan(grid3d, grid3d.extent(0) - 1, full_extent, full_extent));
 zero_2d(submdspan(grid3d, full_extent, grid3d.extent(1) - 1, full_extent));
 zero_2d(submdspan(grid3d, full_extent, full_extent, grid3d.extent(2) - 1));} â *end example*]
