23 Containers library [containers]

23.7 Views [views]

23.7.3 Multidimensional access [views.multidim]

23.7.3.7 submdspan [mdspan.sub]

23.7.3.7.4 Exposition-only helpers [mdspan.sub.helpers]

For a pack p and an integer i, let MAP_RANK(p, i) be the number of elements p...[j] for whose types are not collapsing slice types.
template<class T> concept is-strided-slice = see below;
The concept is-strided-slice<T> is satisfied and modeled if and only if T is a specialization of strided_slice.
template<class IndexType, class S> constexpr auto canonical-index(S s);
Mandates: If S models integral-constant-like, then extents<IndexType>​::​index-cast(S​::​value) is representable as a value of type IndexType.
Preconditions: extents<IndexType>​::​index-cast(std​::​move(s)) is representable as a value of type IndexType.
Effects: Equivalent to:
template<class IndexType, class S> constexpr auto canonical-slice(S s);
Mandates: S is a submdspan slice type for IndexType.
Effects: Equivalent to: if constexpr (is_convertible_v<S, full_extent_t>) { return static_cast<full_extent_t>(std::move(s)); } else if constexpr (is_convertible_v<S, IndexType>) { return canonical-index<IndexType>(std::move(s)); } else if constexpr (is-strided-slice<S>) { auto c_extent = canonical-index<IndexType>(std::move(s.extent)); auto c_offset = canonical-index<IndexType>(std::move(s.offset)); if constexpr (is_same_v<decltype(c_extent), constant_wrapper<IndexType(0)>>) { return strided_slice{ .offset = c_offset, .extent = c_extent, .stride = cw<IndexType(1)> }; } else { return strided_slice{ .offset = c_offset, .extent = c_extent, .stride = canonical-index<IndexType>(std::move(s.stride)) }; } } else { auto [s_first, s_last] = std::move(s); auto c_first = canonical-index<IndexType>(std::move(s_first)); auto c_last = canonical-index<IndexType>(std::move(s_last)); return strided_slice{ .offset = c_first, .extent = canonical-index<IndexType>(c_last - c_first), .stride = cw<IndexType(1)> }; }