24 Containers library [containers]

24.7 Views [views]

24.7.3 Multidimensional access [views.multidim]

24.7.3.7 submdspan [mdspan.sub]

24.7.3.7.7 submdspan function template [mdspan.sub.sub]

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;
Let index_type be typename Extents​::​index_type.
Let sub_map_offset be the result of submdspan_mapping(src.mapping(), slices...).
[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]).
— end note]
Constraints:
  • sizeof...(slices) equals Extents​::​rank(), and
  • the expression submdspan_mapping(src.mapping(), slices...) is well-formed when treated as an unevaluated operand.
Mandates:
  • decltype(submdspan_mapping(src.mapping(), slices...)) is a specialization of submdspan_mapping_result.
  • is_same_v<remove_cvref_t<decltype(sub_map_offset.mapping.extents())>, decltype(submdspan_extents(src.mapping(), slices...))> is true.
  • For each rank index k of src.extents(), exactly one of the following is true:
Preconditions:
  • For each rank index k of src.extents(), all of the following are true:
    • if is a specialization of strided_slice
    • 0  ≤ first_<index_type, k>(slices...)  ≤ last_<k>(src.extents(), slices...)  ≤ src.extent(k)
  • sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...) is true; and
  • 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.
[Note 2: 
These conditions ensure that the mapping returned by submdspan_mapping matches the algorithmically expected index-mapping given the slice specifiers.
— end note]
Effects: Equivalent to: auto sub_map_result = submdspan_mapping(src.mapping(), slices...); return mdspan(src.accessor().offset(src.data(), sub_map_result.offset), sub_map_result.mapping, AccessorPolicy::offset_policy(src.accessor()));
[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.
It does so by reusing a function zero_2d that takes a rank-2 mdspan.
// zero out all elements in an mdspan template<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 surface template<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]