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-extent-slice = see below;
The concept is-extent-slice<T> is satisfied and modeled if and only if T is a specialization of extent_slice.
template<class T> concept is-range-slice = see below;
The concept is-range-slice<T> is satisfied and modeled if and only if T is a specialization of range_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 OffsetType, class SpanType, class... StrideTypes> constexpr auto canonical-range-slice(OffsetType offset, SpanType span, StrideTypes... strides);
Let
  • StrideType denote constant_wrapper<IndexType(1)> if StrideTypes is an empty pack or SpanType denotes constant_wrapper<IndexType(0)>, otherwise StrideTypes...[0];
  • stride be StrideType() if StrideType is a specialization of constant_wrapper, otherwise IndexType(1) if span == 0 is true, otherwise strides...[0];
  • extent-value be 1 + (span - 1) / stride if span != 0 is true, and 0 otherwise; and
  • let extent be cw<IndexType(extent-value)> if both SpanType and StrideType are specializations of constant_wrapper, and IndexType(extent-value) otherwise.
Mandates: sizeof...(StrideTypes) <= 1 is true, and if StrideType is a specialization of constant_wrapper, then StrideType​::​value > 0 is true.
Preconditions: stride > 0 is true.
Returns: extent_slice{.offset = offset, .extent = extent, .stride = stride};
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-extent-slice<S>) { return extent_slice{ .offset = canonical-index<IndexType>(std::move(s.extent)), .extent = canonical-index<IndexType>(std::move(s.offset)), .stride = canonical-index<IndexType>(std::move(s.stride)) }; } else if constexpr (is-range-slice<S>) { auto c_first = canonical-index<IndexType>(std::move(s.first)); auto c_last = canonical-index<IndexType>(std::move(s.last)); return canonical-slice-range<IndexType>( c_first, canonical-index<IndexType>(c_last - c_first), 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 canonical-slice-range<IndexType>( c_first, canonical-index<IndexType>(c_last - c_first)); }