24 Containers library [containers]

24.7 Views [views]

24.7.3 Multidimensional access [views.multidim] submdspan [mdspan.sub] 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]
  • sizeof...(slices) equals Extents​::​rank(), and
  • the expression submdspan_mapping(src.mapping(), slices...) is well-formed when treated as an unevaluated operand.
  • decltype(submdspan_mapping(src.mapping(), slices...)) is a specialization of submd-
  • 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:
  • 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...)  ≤ 
  • 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_offset = submdspan_mapping(src.mapping(), slices...); return mdspan(src.accessor().offset(src.data(), sub_map_offset.offset), sub_map_offset.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]