[views] (original) (raw)

23 Containers library [containers]

23.7 Views [views]


23.7.1 General [views.general]

23.7.2 Contiguous access [views.contiguous]

23.7.2.1 Header synopsis [span.syn]

23.7.2.2 Class template span [views.span]

23.7.2.2.1 Overview [span.overview]

23.7.2.2.2 Constructors, copy, and assignment [span.cons]

23.7.2.2.3 Deduction guides [span.deduct]

23.7.2.2.4 Subviews [span.sub]

23.7.2.2.5 Observers [span.obs]

23.7.2.2.6 Element access [span.elem]

23.7.2.2.7 Iterator support [span.iterators]

23.7.2.3 Views of object representation [span.objectrep]

23.7.3 Multidimensional access [views.multidim]

23.7.3.1 Overview [mdspan.overview]

23.7.3.2 Header synopsis [mdspan.syn]

23.7.3.3 Class template extents [mdspan.extents]

23.7.3.3.1 Overview [mdspan.extents.overview]

23.7.3.3.2 Exposition-only helpers [mdspan.extents.expo]

23.7.3.3.3 Constructors [mdspan.extents.cons]

23.7.3.3.4 Observers of the multidimensional index space [mdspan.extents.obs]

23.7.3.3.5 Comparison operators [mdspan.extents.cmp]

23.7.3.3.6 Alias template dextents [mdspan.extents.dextents]

23.7.3.3.7 Alias template dims [mdspan.extents.dims]

23.7.3.4 Layout mapping [mdspan.layout]

23.7.3.4.1 General [mdspan.layout.general]

23.7.3.4.2 Requirements [mdspan.layout.reqmts]

23.7.3.4.3 Layout mapping policy requirements [mdspan.layout.policy.reqmts]

23.7.3.4.4 Layout mapping policies [mdspan.layout.policy.overview]

23.7.3.4.5 Class template layout_left​::​mapping [mdspan.layout.left]

23.7.3.4.5.1 Overview [mdspan.layout.left.overview]

23.7.3.4.5.2 Constructors [mdspan.layout.left.cons]

23.7.3.4.5.3 Observers [mdspan.layout.left.obs]

23.7.3.4.6 Class template layout_right​::​mapping [mdspan.layout.right]

23.7.3.4.6.1 Overview [mdspan.layout.right.overview]

23.7.3.4.6.2 Constructors [mdspan.layout.right.cons]

23.7.3.4.6.3 Observers [mdspan.layout.right.obs]

23.7.3.4.7 Class template layout_stride​::​mapping [mdspan.layout.stride]

23.7.3.4.7.1 Overview [mdspan.layout.stride.overview]

23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]

23.7.3.4.7.3 Constructors [mdspan.layout.stride.cons]

23.7.3.4.7.4 Observers [mdspan.layout.stride.obs]

23.7.3.4.8 Class template layout_left_padded​::​mapping [mdspan.layout.leftpad]

23.7.3.4.8.1 Overview [mdspan.layout.leftpad.overview]

23.7.3.4.8.2 Exposition-only members [mdspan.layout.leftpad.expo]

23.7.3.4.8.3 Constructors [mdspan.layout.leftpad.cons]

23.7.3.4.8.4 Observers [mdspan.layout.leftpad.obs]

23.7.3.4.9 Class template layout_right_padded​::​mapping [mdspan.layout.rightpad]

23.7.3.4.9.1 Overview [mdspan.layout.rightpad.overview]

23.7.3.4.9.2 Exposition-only members [mdspan.layout.rightpad.expo]

23.7.3.4.9.3 Constructors [mdspan.layout.rightpad.cons]

23.7.3.4.9.4 Observers [mdspan.layout.rightpad.obs]

23.7.3.5 Accessor policy [mdspan.accessor]

23.7.3.5.1 General [mdspan.accessor.general]

23.7.3.5.2 Requirements [mdspan.accessor.reqmts]

23.7.3.5.3 Class template default_accessor [mdspan.accessor.default]

23.7.3.5.3.1 Overview [mdspan.accessor.default.overview]

23.7.3.5.3.2 Members [mdspan.accessor.default.members]

23.7.3.5.4 Class template aligned_accessor [mdspan.accessor.aligned]

23.7.3.5.4.1 Overview [mdspan.accessor.aligned.overview]

23.7.3.5.4.2 Members [mdspan.accessor.aligned.members]

23.7.3.6 Class template mdspan [mdspan.mdspan]

23.7.3.6.1 Overview [mdspan.mdspan.overview]

23.7.3.6.2 Constructors [mdspan.mdspan.cons]

23.7.3.6.3 Members [mdspan.mdspan.members]

23.7.3.7 submdspan [mdspan.sub]

23.7.3.7.1 Overview [mdspan.sub.overview]

23.7.3.7.2 strided_slice [mdspan.sub.strided.slice]

23.7.3.7.3 submdspan_mapping_result [mdspan.sub.map.result]

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

23.7.3.7.5 submdspan slice canonicalization [mdspan.sub.canonical]

23.7.3.7.6 submdspan_extents function [mdspan.sub.extents]

23.7.3.7.7 Specializations of submdspan_mapping [mdspan.sub.map]

23.7.3.7.7.1 Sliceable layout mapping requirements [mdspan.sub.map.sliceable]

23.7.3.7.7.2 Common [mdspan.sub.map.common]

23.7.3.7.7.3 layout_left specialization of submdspan_mapping [mdspan.sub.map.left]

23.7.3.7.7.4 layout_right specialization of submdspan_mapping [mdspan.sub.map.right]

23.7.3.7.7.5 layout_stride specialization of submdspan_mapping [mdspan.sub.map.stride]

23.7.3.7.7.6 layout_left_padded specialization of submdspan_mapping [mdspan.sub.map.leftpad]

23.7.3.7.7.7 layout_right_padded specialization of submdspan_mapping [mdspan.sub.map.rightpad]

23.7.3.7.8 submdspan function template [mdspan.sub.sub]


23.7.1 General [views.general]

The header defines the view span.

The header defines the class template mdspan and other facilities for interacting with these multidimensional views.

In addition to being available via inclusion of the header,dynamic_extent is available when the header is included.

23.7.2 Contiguous access [views.contiguous]

23.7.2.1 Header synopsis [span.syn]

23.7.2.2 Class template span [views.span]

23.7.2.2.1 Overview [span.overview]

A span is a view over a contiguous sequence of objects, the storage of which is owned by some other object.

All member functions of span have constant time complexity.

namespace std { template<class ElementType, size_t Extent = dynamic_extent> class span { public: using element_type = ElementType;using value_type = remove_cv_t<ElementType>;using size_type = size_t;using difference_type = ptrdiff_t;using pointer = element_type*;using const_pointer = const element_type*;using reference = element_type&;using const_reference = const element_type&;using iterator = implementation-defined; using const_iterator = std::const_iterator<iterator>;using reverse_iterator = std::reverse_iterator<iterator>;using const_reverse_iterator = std::const_iterator<reverse_iterator>;static constexpr size_type extent = Extent;constexpr span() noexcept;template<class It> constexpr explicit(extent != dynamic_extent) span(It first, size_type count);template<class It, class End> constexpr explicit(extent != dynamic_extent) span(It first, End last);template<size_t N> constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept;template<class T, size_t N> constexpr span(array<T, N>& arr) noexcept;template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept;template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r);constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il);constexpr span(const span& other) noexcept = default;template<class OtherElementType, size_t OtherExtent> constexpr explicit(see below) span(const span<OtherElementType, OtherExtent>& s) noexcept;constexpr span& operator=(const span& other) noexcept = default;template<size_t Count> constexpr span<element_type, Count> first() const;template<size_t Count> constexpr span<element_type, Count> last() const;template<size_t Offset, size_t Count = dynamic_extent> constexpr span<element_type, _see below_> subspan() const;constexpr span<element_type, dynamic_extent> first(size_type count) const;constexpr span<element_type, dynamic_extent> last(size_type count) const;constexpr span<element_type, dynamic_extent> subspan( size_type offset, size_type count = dynamic_extent) const;constexpr size_type size() const noexcept;constexpr size_type size_bytes() const noexcept;constexpr bool empty() const noexcept;constexpr reference operator[](size_type idx) const;constexpr reference at(size_type idx) const; constexpr reference front() const;constexpr reference back() const;constexpr pointer data() const noexcept;constexpr iterator begin() const noexcept;constexpr iterator end() const noexcept;constexpr const_iterator cbegin() const noexcept { return begin(); } constexpr const_iterator cend() const noexcept { return end(); } constexpr reverse_iterator rbegin() const noexcept;constexpr reverse_iterator rend() const noexcept;constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } constexpr const_reverse_iterator crend() const noexcept { return rend(); } private: pointer data_; size_type size_; };template<class It, class EndOrSize> span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>,maybe-static-ext<EndOrSize>>;template<class T, size_t N> span(T (&)[N]) -> span<T, N>;template<class T, size_t N> span(array<T, N>&) -> span<T, N>;template<class T, size_t N> span(const array<T, N>&) -> span<const T, N>;template<class R> span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;}

ElementType is required to be a complete object type that is not an abstract class type.

For a span s, any operation that invalidates a pointer in the range [s.data(), s.data() + s.size()) invalidates pointers, iterators, and references to elements of s.

23.7.2.2.2 Constructors, copy, and assignment [span.cons]

constexpr span() noexcept;

Constraints: Extent == dynamic_extent || Extent == 0 is true.

Postconditions: size() == 0 && data() == nullptr.

template<class It> constexpr explicit(extent != dynamic_extent) span(It first, size_type count);

Constraints: Let U be remove_reference_t<iter_reference_t<It>>.

Preconditions:

Hardened preconditions: If extent is not equal to dynamic_extent, then count == extent is true.

Effects: Initializes data_ with to_address(first) and_size__ with count.

template<class It, class End> constexpr explicit(extent != dynamic_extent) span(It first, End last);

Constraints: Let U be remove_reference_t<iter_reference_t<It>>.

Preconditions:

Hardened preconditions: If extent is not equal to dynamic_extent, then (last - first) == extent is true.

Effects: Initializes data_ with to_address(first) and_size__ with last - first.

Throws: When and what last - first throws.

template<size_t N> constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept;template<class T, size_t N> constexpr span(array<T, N>& arr) noexcept;template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept;

Constraints: Let U be remove_pointer_t<decltype(std​::​data(arr))>.

Effects: Constructs a span that is a view over the supplied array.

[Note 4:

type_identity_t affects class template argument deduction.

— _end note_]

Postconditions: size() == N && data() == std​::​data(arr) is true.

template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r);

Constraints: Let U be remove_reference_t<ranges​::​range_reference_t<R>>.

Preconditions:

Hardened preconditions: If extent is not equal to dynamic_extent, then ranges​::​size(r) == extent is true.

Effects: Initializes data_ with ranges​::​data(r) and_size__ with ranges​::​size(r).

Throws: What and when ranges​::​data(r) and ranges​::​size(r) throw.

constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il);

Constraints: is_const_v<element_type> is true.

Hardened preconditions: If extent is not equal to dynamic_extent, then il.size() == extent is true.

Effects: Initializes data_ with il.data() and_size__ with il.size().

constexpr span(const span& other) noexcept = default;

Postconditions: other.size() == size() && other.data() == data().

template<class OtherElementType, size_t OtherExtent> constexpr explicit(_see below_) span(const span<OtherElementType, OtherExtent>& s) noexcept;

Constraints:

Hardened preconditions: If extent is not equal to dynamic_extent, then s.size() == extent is true.

Effects: Constructs a span that is a view over the range [s.data(), s.data() + s.size()).

Postconditions: size() == s.size() && data() == s.data().

Remarks: The expression inside explicit is equivalent to:extent != dynamic_extent && OtherExtent == dynamic_extent

constexpr span& operator=(const span& other) noexcept = default;

Postconditions: size() == other.size() && data() == other.data().

23.7.2.2.3 Deduction guides [span.deduct]

template<class It, class EndOrSize> span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>,[_maybe-static-ext_](#concept:maybe-static-ext "23.7.2.1 Header <span> synopsis [span.syn]")<EndOrSize>>;

template<class R> span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;

23.7.2.2.4 Subviews [span.sub]

template<size_t Count> constexpr span<element_type, Count> first() const;

Mandates: Count <= Extent is true.

Hardened preconditions: Count <= size() is true.

Effects: Equivalent to: return R(data(), Count);where R is the return type.

template<size_t Count> constexpr span<element_type, Count> last() const;

Mandates: Count <= Extent is true.

Hardened preconditions: Count <= size() is true.

Effects: Equivalent to: return R(data() + (size() - Count), Count);where R is the return type.

template<size_t Offset, size_t Count = dynamic_extent> constexpr span<element_type, _see below_> subspan() const;

Mandates: Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset) is true.

Hardened preconditions: Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset) is true.

Effects: Equivalent to:return span<ElementType, _see below_>( data() + Offset, Count != dynamic_extent ? Count : size() - Offset);

Remarks: The second template argument of the returned span type is:Count != dynamic_extent ? Count: (Extent != dynamic_extent ? Extent - Offset: dynamic_extent)

constexpr span<element_type, dynamic_extent> first(size_type count) const;

Hardened preconditions: count <= size() is true.

Effects: Equivalent to: return R(data(), count);where R is the return type.

constexpr span<element_type, dynamic_extent> last(size_type count) const;

Hardened preconditions: count <= size() is true.

Effects: Equivalent to: return R(data() + (size() - count), count);where R is the return type.

constexpr span<element_type, dynamic_extent> subspan( size_type offset, size_type count = dynamic_extent) const;

Hardened preconditions: offset <= size() && (count == dynamic_extent || count <= size() - offset) is true.

Effects: Equivalent to:return R(data() + offset, count == dynamic_extent ? size() - offset : count);where R is the return type.

23.7.2.2.5 Observers [span.obs]

constexpr size_type size() const noexcept;

Effects: Equivalent to: return size_;

constexpr size_type size_bytes() const noexcept;

Effects: Equivalent to: return size() * sizeof(element_type);

constexpr bool empty() const noexcept;

Effects: Equivalent to: return size() == 0;

23.7.2.2.6 Element access [span.elem]

constexpr reference operator[](size_type idx) const;

Hardened preconditions: idx < size() is true.

Returns: *(data() + idx).

constexpr reference at(size_type idx) const;

Returns: *(data() + idx).

Throws: out_of_range if idx >= size() is true.

constexpr reference front() const;

Hardened preconditions: empty() is false.

constexpr reference back() const;

Hardened preconditions: empty() is false.

Returns: *(data() + (size() - 1)).

constexpr pointer data() const noexcept;

23.7.2.2.7 Iterator support [span.iterators]

using iterator = _implementation-defined_;

All requirements on container iterators ([container.reqmts]) apply tospan​::​iterator as well.

constexpr iterator begin() const noexcept;

Returns: An iterator referring to the first element in the span.

If empty() is true, then it returns the same value as end().

constexpr iterator end() const noexcept;

Returns: An iterator which is the past-the-end value.

constexpr reverse_iterator rbegin() const noexcept;

Effects: Equivalent to: return reverse_iterator(end());

constexpr reverse_iterator rend() const noexcept;

Effects: Equivalent to: return reverse_iterator(begin());

23.7.2.3 Views of object representation [span.objectrep]

template<class ElementType, size_t Extent> span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_bytes(span<ElementType, Extent> s) noexcept;

Constraints: is_volatile_v<ElementType> is false.

Effects: Equivalent to: return R{reinterpret_cast<const byte*>(s.data()), s.size_bytes()};where R is the return type.

template<class ElementType, size_t Extent> span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_writable_bytes(span<ElementType, Extent> s) noexcept;

Constraints: is_const_v<ElementType> is false andis_volatile_v<ElementType> is false.

Effects: Equivalent to: return R{reinterpret_cast<byte*>(s.data()), s.size_bytes()};where R is the return type.

23.7.3 Multidimensional access [views.multidim]

23.7.3.1 Overview [mdspan.overview]

A multidimensional index space is a Cartesian product of integer intervals.

Each interval can be represented by a half-open range , where and are the lower and upper bounds of the dimension.

The rank of a multidimensional index space is the number of intervals it represents.

The size of a multidimensional index space is the product of for each dimension iif its rank is greater than 0, and 1 otherwise.

An integer r is a rank index of an index space Sif r is in the range .

A pack of integers idx is a multidimensional index in a multidimensional index space S(or representation thereof) if both of the following are true:

23.7.3.2 Header synopsis [mdspan.syn]

23.7.3.3 Class template extents [mdspan.extents]

23.7.3.3.1 Overview [mdspan.extents.overview]

The class template extents represents a multidimensional index space of rank equal to sizeof...(Extents).

In [views],extents is used synonymously with multidimensional index space.

namespace std { template<class IndexType, size_t... Extents> class extents { public: using index_type = IndexType;using size_type = make_unsigned_t<index_type>;using rank_type = size_t;static constexpr rank_type rank() noexcept { return sizeof...(Extents); } static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); } static constexpr size_t static_extent(rank_type) noexcept;constexpr index_type extent(rank_type) const noexcept;constexpr extents() noexcept = default;template<class OtherIndexType, size_t... OtherExtents> constexpr explicit(see below) extents(const extents<OtherIndexType, OtherExtents...>&) noexcept;template<class... OtherIndexTypes> constexpr explicit extents(OtherIndexTypes...) noexcept;template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) extents(span<OtherIndexType, N>) noexcept;template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) extents(const array<OtherIndexType, N>&) noexcept;template<class OtherIndexType, size_t... OtherExtents> friend constexpr bool operator==(const extents&,const extents<OtherIndexType, OtherExtents...>&) noexcept;constexpr size_t fwd-prod-of-extents(rank_type) const noexcept; constexpr size_t rev-prod-of-extents(rank_type) const noexcept; template<class OtherIndexType> static constexpr auto index-cast(OtherIndexType&&) noexcept; private: static constexpr rank_type dynamic-index(rank_type) noexcept; static constexpr rank_type dynamic-index-inv(rank_type) noexcept; array<index_type, rank_dynamic()> dynamic-extents{}; };template<class... Integrals> explicit extents(Integrals...) -> see below;}

Mandates:

Each specialization of extents models regular and is trivially copyable.

Let be the element of Extents.

is a dynamic extent if it is equal to dynamic_extent, otherwise is a static extent.

Let be the value of _dynamic-extents_[dynamic-index(r)]if is a dynamic extent, otherwise .

The interval of the multidimensional index space represented by an extents object is .

23.7.3.3.2 Exposition-only helpers [mdspan.extents.expo]

static constexpr rank_type _dynamic-index_(rank_type i) noexcept;

Preconditions: i <= rank() is true.

Returns: The number of with for which is a dynamic extent.

static constexpr rank_type _dynamic-index-inv_(rank_type i) noexcept;

Preconditions: i < rank_dynamic() is true.

Returns: The minimum value of rsuch that dynamic-index(r + 1) == i + 1 is true.

constexpr size_t _fwd-prod-of-extents_(rank_type i) const noexcept;

Preconditions: i <= rank() is true.

Returns: If i > 0 is true, the product of extent(k) for all k in the range [0, i), otherwise 1.

constexpr size_t _rev-prod-of-extents_(rank_type i) const noexcept;

Preconditions: i < rank() is true.

Returns: If i + 1 < rank() is true, the product of extent(k)for all k in the range [i + 1, rank()), otherwise 1.

template<class OtherIndexType> static constexpr auto _index-cast_(OtherIndexType&& i) noexcept;

Effects:

[Note 1:

This function will always return an integral type other than bool.

Since this function's call sites are constrained on convertibility of OtherIndexType to index_type, integer-class types can use the static_cast branch without loss of precision.

— _end note_]

23.7.3.3.3 Constructors [mdspan.extents.cons]

template<class OtherIndexType, size_t... OtherExtents> constexpr explicit(_see below_) extents(const extents<OtherIndexType, OtherExtents...>& other) noexcept;

Constraints:

Preconditions:

Postconditions: *this == other is true.

Remarks: The expression inside explicit is equivalent to:(((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || (numeric_limits<index_type>::max() < numeric_limits<OtherIndexType>::max())

template<class... OtherIndexTypes> constexpr explicit extents(OtherIndexTypes... exts) noexcept;

Let N be sizeof...(OtherIndexTypes), and let exts_arr bearray<index_type, N>{static_cast<
index_type>(std​::​move(exts))...}.

Constraints:

Preconditions:

Postconditions: *this == extents(exts_arr) is true.

template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) extents(span<OtherIndexType, N> exts) noexcept;template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) extents(const array<OtherIndexType, N>& exts) noexcept;

Constraints:

Preconditions:

Effects:

template<class... Integrals> explicit extents(Integrals...) -> _see below_;

Constraints: (is_convertible_v<Integrals, size_t> && ...) is true.

Remarks: The deduced type is extents<size_t, maybe-static-ext<Integrals>...>.

23.7.3.3.4 Observers of the multidimensional index space [mdspan.extents.obs]

static constexpr size_t static_extent(rank_type i) noexcept;

Preconditions: i < rank() is true.

constexpr index_type extent(rank_type i) const noexcept;

Preconditions: i < rank() is true.

23.7.3.3.5 Comparison operators [mdspan.extents.cmp]

template<class OtherIndexType, size_t... OtherExtents> friend constexpr bool operator==(const extents& lhs,const extents<OtherIndexType, OtherExtents...>& rhs) noexcept;

Returns: true if lhs.rank() equals rhs.rank() and if lhs.extent(r) equals rhs.extent(r)for every rank index r of rhs, otherwise false.

23.7.3.3.6 Alias template dextents [mdspan.extents.dextents]

template<class IndexType, size_t Rank> using dextents = _see below_;

Result: A type E that is a specialization of extentssuch that E​::​rank() == Rank && E​::​rank() == E​::​rank_dynamic() is true, andE​::​index_type denotes IndexType.

23.7.3.3.7 Alias template dims [mdspan.extents.dims]

template<size_t Rank, class IndexType = size_t> using dims = _see below_;

Result: A type E that is a specialization of extentssuch that E​::​rank() == Rank && E​::​rank() == E​::​rank_dynamic() is true, andE​::​index_type denotes IndexType.

23.7.3.4 Layout mapping [mdspan.layout]

23.7.3.4.1 General [mdspan.layout.general]

In [mdspan.layout.reqmts] through [mdspan.layout.stride]:

23.7.3.4.2 Requirements [mdspan.layout.reqmts]

A type M meets the layout mapping requirements if

Result: A type that is a specialization of extents.

Result: typename M​::​extents_type​::​index_type.

Result: typename M​::​extents_type​::​rank_type.

Result: A type MP that meets the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) and for which is-mapping-of<MP, M> is true.

Result: const typename M​::​extents_type&

Result: typename M​::​index_type

Returns: A nonnegative integer less than numeric_limits<typename M​::​index_type>​::​max() and less than or equal to numeric_limits<size_t>​::​max().

m(i...) == m(static_cast<typename M::index_type>(i)...)

Result: typename M​::​index_type

Returns: If the size of the multidimensional index space m.extents() is 0, then 0, else 1 plus the maximum value of m(i...) for all i.

Returns: true only if for every i and j where (i != j || ...) is true,m(i...) != m(j...) is true.

[Note 1:

A mapping can return false even if the condition is met.

For certain layouts, it is possibly not feasible to determine efficiently whether the layout is unique.

— _end note_]

Returns: true only if for all k in the range [0, m.required_span_size())there exists an i such that m(i...) equals k.

[Note 2:

A mapping can return false even if the condition is met.

For certain layouts, it is possibly not feasible to determine efficiently whether the layout is exhaustive.

— _end note_]

Returns: true only if for every rank index r of m.extents() there exists an integer such that, for all i where is a multidimensional index in m.extents() ([mdspan.overview]),m((i + )...) - m(i...) equals .

[Note 3:

This implies that for a strided layout.

— _end note_]

[Note 4:

A mapping can return false even if the condition is met.

For certain layouts, it is possibly not feasible to determine efficiently whether the layout is strided.

— _end note_]

Preconditions: m.is_strided() is true.

Result: typename M​::​index_type

Returns: as defined in m.is_strided() above.

[Note 5:

It is not required for m.stride(r) to be well-formed if m.extents().rank() is zero, even if m.is_always_strided() is true.

— _end note_]

Returns: true only if m.is_unique() is truefor all possible objects m of type M.

[Note 6:

A mapping can return false even if the above condition is met.

For certain layout mappings, it is possibly not feasible to determine whether every instance is unique.

— _end note_]

M::is_always_exhaustive()

Returns: true only if m.is_exhaustive() is truefor all possible objects m of type M.

[Note 7:

A mapping can return false even if the above condition is met.

For certain layout mappings, it is possibly not feasible to determine whether every instance is exhaustive.

— _end note_]

Returns: true only if m.is_strided() is truefor all possible objects m of type M.

[Note 8:

A mapping can return false even if the above condition is met.

For certain layout mappings, it is possibly not feasible to determine whether every instance is strided.

— _end note_]

23.7.3.4.3 Layout mapping policy requirements [mdspan.layout.policy.reqmts]

A type MP meets the layout mapping policy requirements if for a type E that is a specialization of extents,MP​::​mapping<E> is valid and denotes a type Xthat meets the layout mapping requirements ([mdspan.layout.reqmts]), and for which the qualified-id X​::​layout_type is valid and denotes the type MP and the qualified-id X​::​extents_type denotes E.

23.7.3.4.4 Layout mapping policies [mdspan.layout.policy.overview]

namespace std { struct layout_left { template<class Extents> class mapping;};struct layout_right { template<class Extents> class mapping;};struct layout_stride { template<class Extents> class mapping;};template<size_t PaddingValue> struct layout_left_padded { template<class Extents> class mapping;};template<size_t PaddingValue> struct layout_right_padded { template<class Extents> class mapping;};}

Each of layout_left, layout_right, and layout_stride, as well as each specialization oflayout_left_padded and layout_right_padded, meets the layout mapping policy requirements and is a trivially copyable type.

Furthermore,is_trivially_default_constructible_v<T> is truefor any such type T.

23.7.3.4.5 Class template layout_left​::​mapping [mdspan.layout.left]

23.7.3.4.5.1 Overview [mdspan.layout.left.overview]

layout_left provides a layout mapping where the leftmost extent has stride 1, and strides increase left-to-right as the product of extents.

namespace std { template<class Extents> class layout_left::mapping { public: using extents_type = Extents;using index_type = extents_type::index_type;using size_type = extents_type::size_type;using rank_type = extents_type::rank_type;using layout_type = layout_left;constexpr mapping() noexcept = default;constexpr mapping(const mapping&) noexcept = default;constexpr mapping(const extents_type&) noexcept;template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>&) noexcept;template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>&) noexcept;template<class LayoutLeftPaddedMapping> constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>) mapping(const LayoutLeftPaddedMapping&) noexcept;template<class OtherExtents> constexpr explicit(see below) mapping(const layout_stride::mapping<OtherExtents>&);constexpr mapping& operator=(const mapping&) noexcept = default;constexpr const extents_type& extents() const noexcept { return extents_; } constexpr index_type required_span_size() const noexcept;template<class... Indices> constexpr index_type operator()(Indices...) const noexcept;static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept { return true; } static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } static constexpr bool is_exhaustive() noexcept { return true; } static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept;template<class OtherExtents> friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;private: extents_type extents_{}; template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const -> see below;template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...);} };}

If Extents is not a specialization of extents, then the program is ill-formed.

layout_left​::​mapping<E> is a trivially copyable type that models regular for each E.

Mandates: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents()is representable as a value of type typename Extents​::​index_type.

23.7.3.4.5.2 Constructors [mdspan.layout.left.cons]

constexpr mapping(const extents_type& e) noexcept;

Preconditions: The size of the multidimensional index space eis representable as a value of type index_type ([basic.fundamental]).

Effects: Direct-non-list-initializes extents_ with e.

template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>& other) noexcept;

Constraints: is_constructible_v<extents_type, OtherExtents> is true.

Preconditions: other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).

Effects: Direct-non-list-initializes extents_ with other.extents().

template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>& other) noexcept;

Constraints:

Preconditions: other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).

Effects: Direct-non-list-initializes extents_ with other.extents().

template<class LayoutLeftPaddedMapping> constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>) mapping(const LayoutLeftPaddedMapping&) noexcept;

Constraints:

Mandates: If

then Extents​::​static_extent(0) equalsLayoutLeftPaddedMapping​::​static-padding-stride.

Preconditions:

Effects: Direct-non-list-initializes extents_ with other.extents().

template<class OtherExtents> constexpr explicit(_see below_) mapping(const layout_stride::mapping<OtherExtents>& other);

Constraints: is_constructible_v<extents_type, OtherExtents> is true.

Preconditions:

Effects: Direct-non-list-initializes extents_ with other.extents().

Remarks: The expression inside explicit is equivalent to:!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)

23.7.3.4.5.3 Observers [mdspan.layout.left.obs]

constexpr index_type required_span_size() const noexcept;

Returns: extents().fwd-prod-of-extents(extents_type​::​rank()).

template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;

Constraints:

Preconditions: extents_type​::​index-cast(i) is a multidimensional index in extents_ ([mdspan.overview]).

Effects: Let P be a parameter pack such thatis_same_v<index_sequence_for<Indices...>, index_sequence<P...>> is true.

Equivalent to:return ((static_cast<index_type>(i) * stride(P)) + ... + 0);

constexpr index_type stride(rank_type i) const noexcept;

Constraints: extents_type​::​rank() > 0 is true.

Preconditions: i < extents_type​::​rank() is true.

Returns: extents().fwd-prod-of-extents(i).

template<class OtherExtents> friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;

Constraints: extents_type​::​rank() == OtherExtents​::​rank() is true.

Effects: Equivalent to: return x.extents() == y.extents();

23.7.3.4.6 Class template layout_right​::​mapping [mdspan.layout.right]

23.7.3.4.6.1 Overview [mdspan.layout.right.overview]

layout_right provides a layout mapping where the rightmost extent is stride 1, and strides increase right-to-left as the product of extents.

namespace std { template<class Extents> class layout_right::mapping { public: using extents_type = Extents;using index_type = extents_type::index_type;using size_type = extents_type::size_type;using rank_type = extents_type::rank_type;using layout_type = layout_right;constexpr mapping() noexcept = default;constexpr mapping(const mapping&) noexcept = default;constexpr mapping(const extents_type&) noexcept;template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>&) noexcept;template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>&) noexcept;template<class LayoutRightPaddedMapping> constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>) mapping(const LayoutRightPaddedMapping&) noexcept;template<class OtherExtents> constexpr explicit(see below) mapping(const layout_stride::mapping<OtherExtents>&) noexcept;constexpr mapping& operator=(const mapping&) noexcept = default;constexpr const extents_type& extents() const noexcept { return extents_; } constexpr index_type required_span_size() const noexcept;template<class... Indices> constexpr index_type operator()(Indices...) const noexcept;static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept { return true; } static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } static constexpr bool is_exhaustive() noexcept { return true; } static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept;template<class OtherExtents> friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;private: extents_type extents_{}; template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const -> see below;template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...);} };}

If Extents is not a specialization of extents, then the program is ill-formed.

layout_right​::​mapping<E> is a trivially copyable type that models regular for each E.

Mandates: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents()is representable as a value of type typename Extents​::​index_type.

23.7.3.4.6.2 Constructors [mdspan.layout.right.cons]

constexpr mapping(const extents_type& e) noexcept;

Preconditions: The size of the multidimensional index space e is representable as a value of type index_type ([basic.fundamental]).

Effects: Direct-non-list-initializes extents_ with e.

template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>& other) noexcept;

Constraints: is_constructible_v<extents_type, OtherExtents> is true.

Preconditions: other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).

Effects: Direct-non-list-initializes extents_ with other.extents().

template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>& other) noexcept;

Constraints:

Preconditions: other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).

Effects: Direct-non-list-initializes extents_ with other.extents().

template<class LayoutRightPaddedMapping> constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>) mapping(const LayoutRightPaddedMapping&) noexcept;

Constraints:

Mandates: If

then Extents​::​static_extent(Extents​::​rank() - 1) equalsLayoutRightPaddedMapping​::​static-padding-stride.

Preconditions:

Effects: Direct-non-list-initializes extents_ with other.extents().

template<class OtherExtents> constexpr explicit(_see below_) mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;

Constraints: is_constructible_v<extents_type, OtherExtents> is true.

Preconditions:

Effects: Direct-non-list-initializes extents_ with other.extents().

Remarks: The expression inside explicit is equivalent to:!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)

23.7.3.4.6.3 Observers [mdspan.layout.right.obs]

constexpr index_type required_span_size() const noexcept;

Returns: extents().fwd-prod-of-extents(extents_type​::​rank()).

template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;

Constraints:

Preconditions: extents_type​::​index-cast(i) is a multidimensional index in extents_ ([mdspan.overview]).

Effects: Let P be a parameter pack such thatis_same_v<index_sequence_for<Indices...>, index_sequence<P...>> is true.

Equivalent to:return ((static_cast<index_type>(i) * stride(P)) + ... + 0);

constexpr index_type stride(rank_type i) const noexcept;

Constraints: extents_type​::​rank() > 0 is true.

Preconditions: i < extents_type​::​rank() is true.

Returns: extents().rev-prod-of-extents(i).

template<class OtherExtents> friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;

Constraints: extents_type​::​rank() == OtherExtents​::​rank() is true.

Effects: Equivalent to: return x.extents() == y.extents();

23.7.3.4.7 Class template layout_stride​::​mapping [mdspan.layout.stride]

23.7.3.4.7.1 Overview [mdspan.layout.stride.overview]

layout_stride provides a layout mapping where the strides are user-defined.

namespace std { template<class Extents> class layout_stride::mapping { public: using extents_type = Extents;using index_type = extents_type::index_type;using size_type = extents_type::size_type;using rank_type = extents_type::rank_type;using layout_type = layout_stride;private: static constexpr rank_type rank_ = extents_type::rank(); public: constexpr mapping() noexcept;constexpr mapping(const mapping&) noexcept = default;template<class OtherIndexType> constexpr mapping(const extents_type&, span<OtherIndexType, _rank__>) noexcept;template<class OtherIndexType> constexpr mapping(const extents_type&, const array<OtherIndexType, _rank__>&) noexcept;template<class StridedLayoutMapping> constexpr explicit(see below) mapping(const StridedLayoutMapping&) noexcept;constexpr mapping& operator=(const mapping&) noexcept = default;constexpr const extents_type& extents() const noexcept { return extents_; } constexpr array<index_type, _rank__> strides() const noexcept { return strides_; } constexpr index_type required_span_size() const noexcept;template<class... Indices> constexpr index_type operator()(Indices...) const noexcept;static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept;static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } constexpr bool is_exhaustive() const noexcept;static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type i) const noexcept { return _strides__[i]; } template<class OtherMapping> friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;private: extents_type extents_{}; array<index_type, _rank__> strides_{}; template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const -> see below;template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...);} };}

If Extents is not a specialization of extents, then the program is ill-formed.

layout_stride​::​mapping<E> is a trivially copyable type that models regular for each E.

Mandates: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents()is representable as a value of type typename Extents​::​index_type.

23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]

Let REQUIRED-SPAN-SIZE(e, strides) be:

Let OFFSET(m) be:

Let is-extents be the exposition-only variable template defined as follows:template<class T> constexpr bool is-extents = false; template<class IndexType, size_t... Args> constexpr bool is-extents<extents<IndexType, Args...>> = true;

Let layout-mapping-alike be the exposition-only concept defined as follows:template<class M> concept layout-mapping-alike = requires { requires is-extents<typename M::extents_type>;{ M::is_always_strided() } -> same_as<bool>;{ M::is_always_exhaustive() } -> same_as<bool>;{ M::is_always_unique() } -> same_as<bool>; bool_constant<M::is_always_strided()>::value; bool_constant<M::is_always_exhaustive()>::value; bool_constant<M::is_always_unique()>::value;};

[Note 1:

This concept checks that the functionsM​::​is_always_strided(),M​::​is_always_exhaustive(), andM​::​is_always_unique() exist, are constant expressions, and have a return type of bool.

— _end note_]

23.7.3.4.7.3 Constructors [mdspan.layout.stride.cons]

constexpr mapping() noexcept;

Preconditions: layout_right​::​mapping<extents_type>().required_span_size()is representable as a value of type index_type ([basic.fundamental]).

Effects: Direct-non-list-initializes extents_ with extents_type(), and for all d in the range [0, rank_), direct-non-list-initializes _strides__[d] withlayout_right​::​mapping<extents_type>().stride(d).

template<class OtherIndexType> constexpr mapping(const extents_type& e, span<OtherIndexType, _rank_> s) noexcept;template<class OtherIndexType> constexpr mapping(const extents_type& e, const array<OtherIndexType, _rank_>& s) noexcept;

Constraints:

Preconditions:

Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with as_const(s[d]).

template<class StridedLayoutMapping> constexpr explicit(_see below_) mapping(const StridedLayoutMapping& other) noexcept;

Constraints:

Preconditions:

Effects: Direct-non-list-initializes extents_ with other.extents(), and for all d in the range [0, rank_), direct-non-list-initializes _strides__[d]with other.stride(d).

Remarks: The expression inside explicit is equivalent to:!(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> && (is-mapping-of<layout_left, StridedLayoutMapping> || is-mapping-of<layout_right, StridedLayoutMapping> || is-layout-left-padded-mapping-of<StridedLayoutMapping> || is-layout-right-padded-mapping-of<StridedLayoutMapping> || is-mapping-of<layout_stride, StridedLayoutMapping>))

23.7.3.4.7.4 Observers [mdspan.layout.stride.obs]

constexpr index_type required_span_size() const noexcept;

Returns: REQUIRED-SPAN-SIZE(extents(), strides_).

template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;

Constraints:

Preconditions: extents_type​::​index-cast(i) is a multidimensional index in extents_ ([mdspan.overview]).

Effects: Let P be a parameter pack such thatis_same_v<index_sequence_for<Indices...>, index_sequence<P...>> is true.

Equivalent to:return ((static_cast<index_type>(i) * stride(P)) + ... + 0);

static constexpr bool is_always_exhaustive() noexcept;

Returns: true if rank_ is 0 or if there is a rank index r of extents()such that extents_type​::​static_extent(r) is 0, otherwise false.

constexpr bool is_exhaustive() const noexcept;

Returns:

template<class OtherMapping> friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept;

Constraints:

Preconditions: OtherMapping meets the layout mapping requirements ([mdspan.layout.policy.reqmts]).

Returns: true if x.extents() == y.extents() is true,OFFSET(y) == 0 is true, and each of x.stride(r) == y.stride(r) is truefor r in the range [0, x.extents().rank()).

Otherwise, false.

23.7.3.4.8 Class template layout_left_padded​::​mapping [mdspan.layout.leftpad]

23.7.3.4.8.1 Overview [mdspan.layout.leftpad.overview]

layout_left_padded provides a layout mapping that behaves like layout_left​::​mapping, except that the padding stride stride(1)can be greater than or equal to extent(0).

namespace std { template<size_t PaddingValue> template<class Extents> class layout_left_padded<PaddingValue>::mapping { public: static constexpr size_t padding_value = PaddingValue;using extents_type = Extents;using index_type = extents_type::index_type;using size_type = extents_type::size_type;using rank_type = extents_type::rank_type;using layout_type = layout_left_padded<PaddingValue>;private: static constexpr size_t rank_ = extents_type::rank(); static constexpr size_t first-static-extent = extents_type::static_extent(0);static constexpr size_t static-padding-stride = see below; public: constexpr mapping() noexcept : mapping(extents_type{}) {} constexpr mapping(const mapping&) noexcept = default;constexpr mapping(const extents_type&);template<class OtherIndexType> constexpr mapping(const extents_type&, OtherIndexType);template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>&);template<class OtherExtents> constexpr explicit(see below) mapping(const layout_stride::mapping<OtherExtents>&);template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping&);template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping&) noexcept;constexpr mapping& operator=(const mapping&) noexcept = default;constexpr const extents_type& extents() const noexcept { return extents_; } constexpr array<index_type, rank_> strides() const noexcept;constexpr index_type required_span_size() const noexcept;template<class... Indices> constexpr index_type operator()(Indices...) const noexcept;static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept;static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } constexpr bool is_exhaustive() const noexcept;static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept;template<class LayoutLeftPaddedMapping> friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept;private: index_type stride-1 = static-padding-stride; extents_type extents_{}; template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const -> see below;template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...);} };}

If Extents is not a specialization of extents, then the program is ill-formed.

layout_left_padded​::​mapping<E> is a trivially copyable type that models regular for each E.

Throughout [mdspan.layout.leftpad], let P_rank be the following size rank_ parameter pack of size_t values:

Mandates:

23.7.3.4.8.2 Exposition-only members [mdspan.layout.leftpad.expo]

static constexpr size_t _static-padding-stride_ = _see below_;

The value is

index_type _stride-1_ = _static-padding-stride_;

Recommended practice: Implementations should not store this value if static-padding-stride is not dynamic_extent.

[Note 1:

Using extents<index_type, _static-padding-stride_> instead ofindex_type as the type of stride-1 would achieve this.

— _end note_]

23.7.3.4.8.3 Constructors [mdspan.layout.leftpad.cons]

constexpr mapping(const extents_type& ext);

Preconditions:

Effects:

template<class OtherIndexType> constexpr mapping(const extents_type& ext, OtherIndexType pad);

Constraints:

Preconditions:

Effects: Direct-non-list-initializes extents_ with ext, and if rank_ is greater than one, direct-non-list-initializes stride-1 with_LEAST-MULTIPLE-AT-LEAST_(pad, ext.extent(0)).

template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>& other);

Constraints: is_constructible_v<extents_type, OtherExtents> is true.

Mandates: If OtherExtents​::​rank() is greater than 1, then(static-padding-stride == dynamic_extent) || (OtherExtents::static_extent(0) == dynamic_extent) || (static-padding-stride == OtherExtents::static_extent(0)) is true.

Preconditions:

Effects: Equivalent to mapping(other.extents()).

template<class OtherExtents> constexpr explicit(_see below_) mapping(const layout_stride::mapping<OtherExtents>& other);

Constraints: is_constructible_v<extents_type, OtherExtents> is true.

Preconditions:

Effects:

Remarks: The expression inside explicit is equivalent to:!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)

template<class LayoutLeftPaddedMapping> constexpr explicit(_see below_) mapping(const LayoutLeftPaddedMapping& other);

Constraints:

Mandates: If rank_ is greater than 1, thenpadding_value == dynamic_extent ||LayoutLeftPaddedMapping::padding_value == dynamic_extent ||padding_value == LayoutLeftPaddedMapping::padding_valueis true.

Preconditions:

Effects:

Remarks: The expression inside explicit is equivalent to:!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type> ||rank_> 1 && (padding_value != dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent)

template<class LayoutRightPaddedMapping> constexpr explicit(_see below_) mapping(const LayoutRightPaddedMapping& other) noexcept;

Constraints:

Preconditions: other.required_span_size() is representable as a value of type index_type.

Effects: Direct-non-list-initializes extents_ with other.extents().

Remarks: The expression inside explicit is equivalent to:!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>

[Note 1:

Neither the input mapping nor the mapping to be constructed uses the padding stride in the rank-0 or rank-1 case, so the padding stride does not affect either the constraints or the preconditions.

— _end note_]

23.7.3.4.8.4 Observers [mdspan.layout.leftpad.obs]

constexpr array<index_type, _rank_> strides() const noexcept;

Returns: array<index_type, _rank__>({stride(P_rank)...}).

constexpr index_type required_span_size() const noexcept;

Returns:

template<class... Indices> constexpr size_t operator()(Indices... idxs) const noexcept;

Constraints:

Preconditions: extents_type​::​index-cast(idxs) is a multidimensional index in extents() ([mdspan.overview]).

Returns: ((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0).

static constexpr bool is_always_exhaustive() noexcept;

Returns:

constexpr bool is_exhaustive() const noexcept;

Returns: true if rank_ equals zero or one; otherwise, extents_.extent(0) == stride(1).

constexpr index_type stride(rank_type r) const noexcept;

Preconditions: r is smaller than rank_.

Returns:

template<class LayoutLeftPaddedMapping> friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;

Constraints:

Returns: true if x.extents() == y.extents() is true and_rank__ < 2 || x.stride(1) == y.
stride(1) is true.

Otherwise, false.

23.7.3.4.9 Class template layout_right_padded​::​mapping [mdspan.layout.rightpad]

23.7.3.4.9.1 Overview [mdspan.layout.rightpad.overview]

layout_right_padded provides a layout mapping that behaves like layout_right​::​mapping, except that the padding stride stride(extents_type​::​rank() - 2)can be greater than or equal toextents_type​::​extent(extents_type​::​rank() - 1).

namespace std { template<size_t PaddingValue> template<class Extents> class layout_right_padded<PaddingValue>::mapping { public: static constexpr size_t padding_value = PaddingValue;using extents_type = Extents;using index_type = extents_type::index_type;using size_type = extents_type::size_type;using rank_type = extents_type::rank_type;using layout_type = layout_right_padded<PaddingValue>;private: static constexpr size_t rank_ = extents_type::rank(); static constexpr size_t last-static-extent = extents_type::static_extent(rank_ - 1);static constexpr size_t static-padding-stride = see below; public: constexpr mapping() noexcept : mapping(extents_type{}) {} constexpr mapping(const mapping&) noexcept = default;constexpr mapping(const extents_type&);template<class OtherIndexType> constexpr mapping(const extents_type&, OtherIndexType);template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>&);template<class OtherExtents> constexpr explicit(see below) mapping(const layout_stride::mapping<OtherExtents>&);template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping&);template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping&) noexcept;constexpr mapping& operator=(const mapping&) noexcept = default;constexpr const extents_type& extents() const noexcept { return extents_; } constexpr array<index_type, rank_> strides() const noexcept;constexpr index_type required_span_size() const noexcept;template<class... Indices> constexpr index_type operator()(Indices...) const noexcept;static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept;static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } constexpr bool is_exhaustive() const noexcept;static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept;template<class LayoutRightPaddedMapping> friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept;private: index_type stride-rm2 = static-padding-stride; extents_type extents_{}; template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const -> see below;template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...);} };}

If Extents is not a specialization of extents, then the program is ill-formed.

layout_right_padded​::​mapping<E> is a trivially copyable type that models regular for each E.

Throughout [mdspan.layout.rightpad], let P_rank be the following size rank_ parameter pack of size_t values:

Mandates:

23.7.3.4.9.2 Exposition-only members [mdspan.layout.rightpad.expo]

static constexpr size_t _static-padding-stride_ = _see below_;

The value is

index_type _stride-rm2_ = _static-padding-stride_;

Recommended practice: Implementations should not store this value if static-padding-stride is not dynamic_extent.

[Note 1:

Using extents<index_type, _static-padding-stride_>instead of index_type as the type of _stride-rm2_would achieve this.

— _end note_]

23.7.3.4.9.3 Constructors [mdspan.layout.rightpad.cons]

constexpr mapping(const extents_type& ext);

Preconditions:

Effects:

template<class OtherIndexType> constexpr mapping(const extents_type& ext, OtherIndexType pad);

Constraints:

Preconditions:

Effects: Direct-non-list-initializes extents_ with ext, and if rank_ is greater than one, direct-non-list-initializes stride-rm2 with_LEAST-MULTIPLE-AT-LEAST_(pad, ext.extent(rank_ - 1)).

template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>& other);

Constraints: is_constructible_v<extents_type, OtherExtents> is true.

Mandates: If OtherExtents​::​rank() is greater than 1, then(static-padding-stride == dynamic_extent) || (OtherExtents::static_extent(rank_ - 1) == dynamic_extent) || (static-padding-stride == OtherExtents::static_extent(rank_ - 1)) is true.

Preconditions:

Effects: Equivalent to mapping(other.extents()).

template<class OtherExtents> constexpr explicit(_see below_) mapping(const layout_stride::mapping<OtherExtents>& other);

Constraints: is_constructible_v<extents_type, OtherExtents> is true.

Preconditions:

Effects:

Remarks: The expression inside explicit is equivalent to:!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)

template<class LayoutRightPaddedMapping> constexpr explicit(_see below_) mapping(const LayoutRightPaddedMapping& other);

Constraints:

Mandates: If rank_ is greater than 1, thenpadding_value == dynamic_extent ||LayoutRightPaddedMapping::padding_value == dynamic_extent ||padding_value == LayoutRightPaddedMapping::padding_valueis true.

Preconditions:

Effects:

Remarks: The expression inside explicit is equivalent to:!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type> || rank_ > 1 && (padding_value != dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent)

template<class LayoutLeftPaddedMapping> constexpr explicit(_see below_) mapping(const LayoutLeftPaddedMapping& other) noexcept;

Constraints:

Preconditions: other.required_span_size() is representable as a value of type index_type.

Effects: Direct-non-list-initializes extents_ with other.extents().

Remarks: The expression inside explicit is equivalent to:!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>

[Note 1:

Neither the input mapping nor the mapping to be constructed uses the padding stride in the rank-0 or rank-1 case, so the padding stride affects neither the constraints nor the preconditions.

— _end note_]

23.7.3.4.9.4 Observers [mdspan.layout.rightpad.obs]

constexpr array<index_type, _rank_> strides() const noexcept;

Returns: array<index_type, _rank__>(stride(P_rank)...).

constexpr index_type required_span_size() const noexcept;

Returns: 0 if the multidimensional index space extents_ is empty, otherwise (*this)(extents_.extent(P_rank) - index_type(1)...) + 1.

template<class... Indices> constexpr size_t operator()(Indices... idxs) const noexcept;

Constraints:

Preconditions: extents_type​::​index-cast(idxs) is a multidimensional index in extents() ([mdspan.overview]).

Returns: ((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0).

static constexpr bool is_always_exhaustive() noexcept;

Returns:

constexpr bool is_exhaustive() const noexcept;

Returns: true if rank_ equals zero or one; otherwise,extents_.extent(rank_ - 1) == stride(rank_ - 2)

constexpr index_type stride(rank_type r) const noexcept;

Preconditions: r is smaller than rank_.

Returns:

template<class LayoutRightPaddedMapping> friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept;

Constraints:

Returns: true if x.extents() == y.extents() is true and_rank__ < 2 || x.stride(rank_ - 2) == y.stride(rank_ - 2) is true.

Otherwise, false.

23.7.3.5 Accessor policy [mdspan.accessor]

23.7.3.5.1 General [mdspan.accessor.general]

An accessor policy defines types and operations by which a reference to a single object is created from an abstract data handle to a number of such objects and an index.

A range of indices is an accessible range of a given data handle and an accessor if, for each i in the range, the accessor policy's access function produces a valid reference to an object.

23.7.3.5.2 Requirements [mdspan.accessor.reqmts]

A type A meets the accessor policy requirements if

Result: A complete object type that is not an abstract class type.

typename A::data_handle_type

Result: A type that models copyable, and for which is_nothrow_move_constructible_v<A​::​data_handle_type> is true,is_nothrow_move_assignable_v<A​::​data_handle_type> is true, andis_nothrow_swappable_v<A​::​data_handle_type> is true.

[Note 1:

The type of data_handle_type need not be element_type*.

— _end note_]

Result: A type that modelscommon_reference_with<A​::​reference&&, A​::​element_type&>.

[Note 2:

The type of reference need not be element_type&.

— _end note_]

typename A::offset_policy

Result: A type OP such that:

Remarks: The expression is equality preserving.

[Note 3:

Concrete accessor policies can impose preconditions for their access function.

However, they might not.

For example, an accessor wherep is span<A​::​element_type, dynamic_extent> andaccess(p, i) returns p[i % p.size()]does not need to impose a precondition on i.

— _end note_]

Result: A​::​offset_policy​::​data_handle_type

Returns: q such that for b being A​::​offset_policy(a), and any integer n for which [0, n) is an accessible range of p and a:

Remarks: The expression is equality-preserving.

23.7.3.5.3 Class template default_accessor [mdspan.accessor.default]

23.7.3.5.3.1 Overview [mdspan.accessor.default.overview]

namespace std { template<class ElementType> struct default_accessor { using offset_policy = default_accessor;using element_type = ElementType;using reference = ElementType&;using data_handle_type = ElementType*;constexpr default_accessor() noexcept = default;template<class OtherElementType> constexpr default_accessor(default_accessor<OtherElementType>) noexcept;constexpr reference access(data_handle_type p, size_t i) const noexcept;constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;};}

default_accessor meets the accessor policy requirements.

ElementType is required to be a complete object type that is neither an abstract class type nor an array type.

Each specialization of default_accessor is a trivially copyable type that models semiregular.

is an accessible range for an object p of type data_handle_type and an object of type default_accessorif and only if [p, p + n) is a valid range.

23.7.3.5.3.2 Members [mdspan.accessor.default.members]

template<class OtherElementType> constexpr default_accessor(default_accessor<OtherElementType>) noexcept {}

Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]>is true.

constexpr reference access(data_handle_type p, size_t i) const noexcept;

Effects: Equivalent to: return p[i];

constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;

Effects: Equivalent to: return p + i;

23.7.3.5.4 Class template aligned_accessor [mdspan.accessor.aligned]

23.7.3.5.4.1 Overview [mdspan.accessor.aligned.overview]

namespace std { template<class ElementType, size_t ByteAlignment> struct aligned_accessor { using offset_policy = default_accessor<ElementType>;using element_type = ElementType;using reference = ElementType&;using data_handle_type = ElementType*;static constexpr size_t byte_alignment = ByteAlignment;constexpr aligned_accessor() noexcept = default;template<class OtherElementType, size_t OtherByteAlignment> constexpr aligned_accessor( aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;template<class OtherElementType> constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;template<class OtherElementType> constexpr operator default_accessor<OtherElementType>() const noexcept;constexpr reference access(data_handle_type p, size_t i) const noexcept;constexpr typename offset_policy::data_handle_type offset( data_handle_type p, size_t i) const noexcept;};}

Mandates:

aligned_accessor meets the accessor policy requirements.

ElementType is required to be a complete object type that is neither an abstract class type nor an array type.

Each specialization of aligned_accessor is a trivially copyable type that models semiregular.

[0, n) is an accessible range for an object p of type data_handle_type and an object of type aligned_accessor if and only if

[Example 1:

The following function computeuses is_sufficiently_aligned to check whether a given mdspan with default_accessor has a data handle with sufficient alignment to be used with aligned_accessor<float, 4 * sizeof(float)>.

If so, the function dispatches to a function compute_using_fourfold_overalignmentthat requires fourfold over-alignment of arrays, but can therefore use hardware-specific instructions, such as four-wide SIMD (Single Instruction Multiple Data) instructions.

Otherwise, compute dispatches to a possibly less optimized function compute_without_requiring_overalignmentthat has no over-alignment requirement.

void compute_using_fourfold_overalignment( mdspan<float, dims<1>, layout_right, aligned_accessor<float, 4 * alignof(float)>> x);void compute_without_requiring_overalignment( mdspan<float, dims<1>, layout_right> x);void compute(mdspan<float, dims<1>> x) { constexpr auto byte_alignment = 4 * sizeof(float);auto accessor = aligned_accessor<float, byte_alignment>{};auto x_handle = x.data_handle();if (is_sufficiently_aligned<byte_alignment>(x_handle)) { compute_using_fourfold_overalignment(mdspan{x_handle, x.mapping(), accessor});} else { compute_without_requiring_overalignment(x);} } — _end example_]

23.7.3.5.4.2 Members [mdspan.accessor.aligned.members]

template<class OtherElementType, size_t OtherByteAlignment> constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;

Constraints:

template<class OtherElementType> constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;

Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]>is true.

constexpr reference access(data_handle_type p, size_t i) const noexcept;

Preconditions: [0, i + 1) is an accessible range for p and *this.

Effects: Equivalent to: return assume_aligned<byte_alignment>(p)[i];

template<class OtherElementType> constexpr operator default_accessor<OtherElementType>() const noexcept;

Constraints: is_convertible_v<element_type(*)[], OtherElementType(*)[]>is true.

Effects: Equivalent to: return {};

constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const noexcept;

Preconditions: [0, i + 1) is an accessible range for p and *this.

Effects: Equivalent to: return assume_aligned<byte_alignment>(p) + i;

23.7.3.6 Class template mdspan [mdspan.mdspan]

23.7.3.6.1 Overview [mdspan.mdspan.overview]

mdspan is a view of a multidimensional array of elements.

namespace std { template<class ElementType, class Extents, class LayoutPolicy = layout_right,class AccessorPolicy = default_accessor<ElementType>> class mdspan { public: using extents_type = Extents;using layout_type = LayoutPolicy;using accessor_type = AccessorPolicy;using mapping_type = layout_type::template mapping<extents_type>;using element_type = ElementType;using value_type = remove_cv_t<element_type>;using index_type = extents_type::index_type;using size_type = extents_type::size_type;using rank_type = extents_type::rank_type;using data_handle_type = accessor_type::data_handle_type;using reference = accessor_type::reference;static constexpr rank_type rank() noexcept { return extents_type::rank(); } static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); } static constexpr size_t static_extent(rank_type r) noexcept { return extents_type::static_extent(r); } constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); } constexpr mdspan();constexpr mdspan(const mdspan& rhs) = default;constexpr mdspan(mdspan&& rhs) = default;template<class... OtherIndexTypes> constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts);template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span<OtherIndexType, N> exts);template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);constexpr mdspan(data_handle_type p, const extents_type& ext);constexpr mdspan(data_handle_type p, const mapping_type& m);constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);template<class OtherElementType, class OtherExtents,class OtherLayoutPolicy, class OtherAccessorPolicy> constexpr explicit(see below) mdspan(const mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessorPolicy>& other);constexpr mdspan& operator=(const mdspan& rhs) = default;constexpr mdspan& operator=(mdspan&& rhs) = default;template<class... OtherIndexTypes> constexpr reference operator[](OtherIndexTypes... indices) const;template<class OtherIndexType> constexpr reference operator[](span<OtherIndexType, rank()> indices) const;template<class OtherIndexType> constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;template<class... OtherIndexTypes> constexpr reference at(OtherIndexTypes... indices) const; template<class OtherIndexType> constexpr reference at(span<OtherIndexType, rank()> indices) const; template<class OtherIndexType> constexpr reference at(const array<OtherIndexType, rank()>& indices) const; constexpr size_type size() const noexcept;constexpr bool empty() const noexcept;friend constexpr void swap(mdspan& x, mdspan& y) noexcept;constexpr const extents_type& extents() const noexcept { return map_.extents(); } constexpr const data_handle_type& data_handle() const noexcept { return ptr_; } constexpr const mapping_type& mapping() const noexcept { return map_; } constexpr const accessor_type& accessor() const noexcept { return acc_; } static constexpr bool is_always_unique() { return mapping_type::is_always_unique(); } static constexpr bool is_always_exhaustive() { return mapping_type::is_always_exhaustive(); } static constexpr bool is_always_strided() { return mapping_type::is_always_strided(); } constexpr bool is_unique() const { return map_.is_unique(); } constexpr bool is_exhaustive() const { return map_.is_exhaustive(); } constexpr bool is_strided() const { return map_.is_strided(); } constexpr index_type stride(rank_type r) const { return map_.stride(r); } private: accessor_type acc_; mapping_type map_; data_handle_type ptr_; };template<class CArray> requires (is_array_v<CArray> && rank_v<CArray> == 1) mdspan(CArray&) -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;template<class Pointer> requires (is_pointer_v<remove_reference_t<Pointer>>) mdspan(Pointer&&) -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;template<class ElementType, class... Integrals> requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0) explicit mdspan(ElementType*, Integrals...) -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>;template<class ElementType, class OtherIndexType, size_t N> mdspan(ElementType*, span<OtherIndexType, N>) -> mdspan<ElementType, dextents<size_t, N>>;template<class ElementType, class OtherIndexType, size_t N> mdspan(ElementType*, const array<OtherIndexType, N>&) -> mdspan<ElementType, dextents<size_t, N>>;template<class ElementType, class IndexType, size_t... ExtentsPack> mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&) -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;template<class ElementType, class MappingType> mdspan(ElementType*, const MappingType&) -> mdspan<ElementType, typename MappingType::extents_type,typename MappingType::layout_type>;template<class MappingType, class AccessorType> mdspan(const typename AccessorType::data_handle_type&, const MappingType&,const AccessorType&) -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,typename MappingType::layout_type, AccessorType>;}

Mandates:

LayoutPolicy shall meet the layout mapping policy requirements ([mdspan.layout.policy.reqmts]), andAccessorPolicy shall meet the accessor policy requirements ([mdspan.accessor.reqmts]).

Each specialization MDS of mdspan models copyable and

A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_typeare trivially copyable types.

23.7.3.6.2 Constructors [mdspan.mdspan.cons]

Constraints:

Preconditions: [0, _map__.required_span_size()) is an accessible range of _ptr__ and _acc__for the values of _map__ and _acc__after the invocation of this constructor.

Effects: Value-initializes ptr_, map_, and acc_.

template<class... OtherIndexTypes> constexpr explicit mdspan(data_handle_type p, OtherIndexTypes... exts);

Let N be sizeof...(OtherIndexTypes).

Constraints:

Preconditions: [0, _map__.required_span_size()) is an accessible range of p and _acc__for the values of _map__ and _acc__after the invocation of this constructor.

Effects:

template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span<OtherIndexType, N> exts);template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);

Constraints:

Preconditions: [0, _map__.required_span_size()) is an accessible range of p and _acc__for the values of _map__ and _acc__after the invocation of this constructor.

Effects:

constexpr mdspan(data_handle_type p, const extents_type& ext);

Constraints:

Preconditions: [0, _map__.required_span_size()) is an accessible range of p and _acc__for the values of _map__ and _acc__after the invocation of this constructor.

Effects:

constexpr mdspan(data_handle_type p, const mapping_type& m);

Constraints: is_default_constructible_v<accessor_type> is true.

Preconditions: [0, m.required_span_size()) is an accessible range of p and _acc__for the value of _acc__ after the invocation of this constructor.

Effects:

constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);

Preconditions: [0, m.required_span_size()) is an accessible range of p and a.

Effects:

template<class OtherElementType, class OtherExtents,class OtherLayoutPolicy, class OtherAccessor> constexpr explicit(_see below_) mdspan(const mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessor>& other);

Constraints:

Mandates:

Preconditions: [0, _map__.required_span_size()) is an accessible range of _ptr__ and _acc__for values of _ptr__, _map__, and _acc__after the invocation of this constructor.

Hardened preconditions: For each rank index r of extents_type,static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)is true.

Effects:

Remarks: The expression inside explicit is equivalent to:!is_convertible_v<const OtherLayoutPolicy::template mapping<OtherExtents>&, mapping_type> || !is_convertible_v<const OtherAccessor&, accessor_type>

23.7.3.6.3 Members [mdspan.mdspan.members]

template<class... OtherIndexTypes> constexpr reference operator[](OtherIndexTypes... indices) const;

Constraints:

Let I be extents_type​::​index-cast(std​::​move(indices)).

Hardened preconditions: I is a multidimensional index in extents().

[Note 1:

This implies that_map__(I) < map_.required_span_size()is true.

— _end note_]

Effects: Equivalent to:return acc_.access(ptr_, map_(static_cast<index_type>(std::move(indices))...));

template<class OtherIndexType> constexpr reference operator[](span<OtherIndexType, rank()> indices) const;template<class OtherIndexType> constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;

Constraints:

Effects: Let P be a parameter pack such thatis_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true.

Equivalent to:return operator[](extents_type::_index-cast_(as_const(indices[P]))...);

template<class... OtherIndexTypes> constexpr reference at(OtherIndexTypes... indices) const;

Constraints:

Let I be extents_type​::​index-cast(std​::​move(indices)).

Throws: out_of_range if I is not a multidimensional index in extents().

template<class OtherIndexType> constexpr reference at(span<OtherIndexType, rank()> indices) const;template<class OtherIndexType> constexpr reference at(const array<OtherIndexType, rank()>& indices) const;

Constraints:

Effects: Let P be a parameter pack such thatis_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true.

Equivalent to:return at(extents_type::index-cast(as_const(indices[P]))...);

constexpr size_type size() const noexcept;

Preconditions: The size of the multidimensional index space extents()is representable as a value of type size_type ([basic.fundamental]).

Returns: extents().fwd-prod-of-extents(rank()).

constexpr bool empty() const noexcept;

Returns: trueif the size of the multidimensional index space extents() is 0, otherwise false.

friend constexpr void swap(mdspan& x, mdspan& y) noexcept;

Effects: Equivalent to:swap(x.ptr_, y.ptr_); swap(x.map_, y.map_); swap(x.acc_, y.acc_);

23.7.3.7 submdspan [mdspan.sub]

23.7.3.7.1 Overview [mdspan.sub.overview]

The submdspan facilities create a new mdspanviewing a subset of elements of an existing input mdspan.

The subset viewed by the created mdspan is determined by the SliceSpecifier arguments.

Given a signed or unsigned integer type IndexType, a type S is asubmdspan slice type for IndexTypeif at least one of the following holds:

Given a signed or unsigned integer type IndexType, a type S is acanonical submdspan index type for IndexTypeif S is either IndexType or constant_wrapper<v>for some value v of type IndexType, such that v is greater than or equal to zero.

Given a signed or unsigned integer type IndexType, a type S is acanonical submdspan slice type for IndexTypeif exactly one of the following is true:

A type S is a collapsing slice type if it is neither full_extent_t nor a specialization of strided_slice.

[Note 1:

Each collapsing slice type in submdspan_mapping's parameter pack of slice specifier types reduces the rank of the result of submdspan_mapping by one.

— _end note_]

A type S is a unit-stride slice type if

Given an object e of type E that is a specialization of extents, and an object s of type Sthat is a canonical submdspan slice type for E​::​index_type, the submdspan slice range of s for the extent of eis:

Given a type E that is a specialization of extents, a type S is avalid submdspan slice type for the extent of Eif S is a canonical slice type for E​::​index_type, and for x equal to E​::​static_extent(k), either x is equal to dynamic_extent; or

Given an object e of type Ethat is a specialization of extents and an object s of type S,s is avalid submdspan slice for the extent of eif

23.7.3.7.2 strided_slice [mdspan.sub.strided.slice]

strided_slice represents a set ofextent regularly spaced integer indices.

The indices start at offset, and increase by increments of stride.

namespace std { template<class OffsetType, class ExtentType, class StrideType> struct strided_slice { using offset_type = OffsetType;using extent_type = ExtentType;using stride_type = StrideType;[[no_unique_address]] offset_type offset{};[[no_unique_address]] extent_type extent{};[[no_unique_address]] stride_type stride{};};}

strided_slice has the data members and special members specified above.

It has no base classes or members other than those specified.

Mandates: OffsetType, ExtentType, and StrideTypeare signed or unsigned integer types, or model integral-constant-like.

[Note 1:

strided_slice{.offset = 1, .extent = 10, .stride = 3}indicates the indices 1, 4, 7, and 10.

Indices are selected from the half-open interval [1, 1 + 10).

— _end note_]

23.7.3.7.3 submdspan_mapping_result [mdspan.sub.map.result]

Specializations of submdspan_mapping_resultare returned by overloads of submdspan_mapping.

namespace std { template<class LayoutMapping> struct submdspan_mapping_result { [[no_unique_address]] LayoutMapping mapping = LayoutMapping(); size_t offset{};};}

submdspan_mapping_result has the data members and special members specified above.

It has no base classes or members other than those specified.

LayoutMapping shall meet the layout mapping requirements ([mdspan.layout.policy.reqmts]).

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_](#concept:is-strided-slice "23.7.3.7.4 Exposition-only helpers [mdspan.sub.helpers]") = _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)> };}

23.7.3.7.5 submdspan slice canonicalization [mdspan.sub.canonical]

template<class IndexType, size_t... Extents, class... SliceSpecifiers> constexpr auto submdspan_canonicalize_slices(const extents<IndexType, Extents...>& src, SliceSpecifiers... slices);

Constraints: sizeof...(SliceSpecifiers) equals sizeof...(Extents).

Mandates: For each rank index k of src:

Preconditions: For each rank index k of src,canonical-slice<IndexType>(slices...[k])is a valid submdspan slice for the extent of src.

Returns: make_tuple(canonical-slice<IndexType>(slices)...).

23.7.3.7.6 submdspan_extents function [mdspan.sub.extents]

template<class IndexType, size_t... Extents, class... SliceSpecifiers> constexpr auto submdspan_extents(const extents<IndexType, Extents...>& src, SliceSpecifiers... raw_slices);

Let slices be the pack introduced by the following declaration:auto [...slices] = submdspan_canonicalize_slices(src, raw_slices...);

Constraints: sizeof...(SliceSpecifiers) equals sizeof...(Extents).

Mandates: For each rank index k of src:

Preconditions: For each rank index k of src,slices...[k] is a valid submdspan slice for the extent of src.

Let SubExtents be a specialization of extents such that:

Returns: A value ext of type SubExtents such that for each rank index k of extents<IndexType, Extents...>, where the type of slices...[k] is not a collapsing slice type,ext.extent(MAP_RANK(slices, k))equals the following, where denotes slices...[k]:

23.7.3.7.7 Specializations of submdspan_mapping [mdspan.sub.map]

23.7.3.7.7.1 Sliceable layout mapping requirements [mdspan.sub.map.sliceable]

Let:

For the purpose of this section, the meaning of submdspan_mapping is established as if by performing argument-dependent lookup only ([basic.lookup.argdep]).

A type M meets the sliceable layout mapping requirements if

Result: A type SMR that is a specialization of type submdspan_mapping_result for some type SM such that

Returns: An object smr of type SMR such that

template<class LayoutMapping> concept [_sliceable-mapping_](#concept:sliceable-mapping "23.7.3.7.7.1 Sliceable layout mapping requirements [mdspan.sub.map.sliceable]") = _see below_;

Let lm be an object of type LayoutMappingand let fe denote a pack of objects of type full_extent_tfor which sizeof...(fe) == LayoutMapping​::​extents_type​::​rank() is true.

A type LayoutMapping satisfies sliceable-mapping if

A type LayoutMapping models sliceable-mappingif LayoutMapping meets the sliceable layout mapping requirements.

23.7.3.7.7.2 Common [mdspan.sub.map.common]

The following elements apply to all functions in [mdspan.sub.map].

Constraints: sizeof...(SpliceSpecifiers) equals extents_type​::​rank().

Mandates: For each rank index k of extents(),SliceSpecifiers...[k] is a valid submdspan slice type for the extent of Extents.

Preconditions: For each rank index k of extents(),slices...[k] is a valid slice for the extent of extents().

Let sub_ext be the result of submdspan_extents(extents(), slices...) and let SubExtents be decltype(sub_ext).

Let sub_strides be an array<SubExtents​::​index_type, SubExtents​::​rank()>such that for each rank index k of extents()for which the type of slices...[k] is not a collapsing slice type,sub_strides[MAP_RANK(slices,k)] equals:

Let ls be a pack of values of index_type, where the element equals the lower bound of the submdspan slice range of slices...[ρ]for extent ρ of extents().

If ls...[k]equals extents().extent(k)for any rank index k of extents(), then let offset be a value of type size_t equal torequired_span_size().

Otherwise, let offset be a value of type size_t equal tooperator()(ls...).

23.7.3.7.7.3 layout_left specialization of submdspan_mapping [mdspan.sub.map.left]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_left::mapping<Extents>::_submdspan-mapping-impl_( SliceSpecifiers... slices) const -> _see below_;

Returns:

23.7.3.7.7.4 layout_right specialization of submdspan_mapping [mdspan.sub.map.right]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_right::mapping<Extents>::_submdspan-mapping-impl_( SliceSpecifiers... slices) const -> _see below_;

Returns:

23.7.3.7.7.5 layout_stride specialization of submdspan_mapping [mdspan.sub.map.stride]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_stride::mapping<Extents>::_submdspan-mapping-impl_( SliceSpecifiers... slices) const -> _see below_;

Returns:

23.7.3.7.7.6 layout_left_padded specialization of submdspan_mapping [mdspan.sub.map.leftpad]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_left_padded::mapping<Extents>::_submdspan-mapping-impl_( SliceSpecifiers... slices) const -> _see below_;

Returns:

23.7.3.7.7.7 layout_right_padded specialization of submdspan_mapping [mdspan.sub.map.rightpad]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_right_padded::mapping<Extents>::_submdspan-mapping-impl_( SliceSpecifiers... slices) const -> _see below_;

Returns:

23.7.3.7.8 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 slices be the pack introduced by the following declaration:auto [...slices] = submdspan_canonicalize_slices(src, raw_slices...);

Let sub_map_offset be the result ofsubmdspan_mapping(src.mapping(), slices...).

[Note 1:

This invocation of submdspan_mappingselects 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:

Mandates: For each rank index k of src:

Preconditions: For each rank index k of src.extents(),slices...[k] is a valid submdspan slice for the extent of src.extents().

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()));

[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_2dthat takes a rank-2 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;} 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_]