[mdspan.mdspan] # 23 Containers library [[containers]](./#containers) ## 23.7 Views [[views]](views#mdspan.mdspan) ### 23.7.3 Multidimensional access [[views.multidim]](views.multidim#mdspan.mdspan) #### 23.7.3.6 Class template mdspan [mdspan.mdspan] #### [23.7.3.6.1](#overview) Overview [[mdspan.mdspan.overview]](mdspan.mdspan.overview) [1](#overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24629) mdspan is a view of a multidimensional array of elements[.](#overview-1.sentence-1) namespace std {template>class mdspan {public:using extents_type = Extents; using layout_type = LayoutPolicy; using accessor_type = AccessorPolicy; using mapping_type = typename layout_type::template mapping; using element_type = ElementType; using value_type = remove_cv_t; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using data_handle_type = typename accessor_type::data_handle_type; using reference = typename 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); }// [[mdspan.mdspan.cons]](#cons "23.7.3.6.2 Constructors"), constructorsconstexpr mdspan(); constexpr mdspan(const mdspan& rhs) = default; constexpr mdspan(mdspan&& rhs) = default; templateconstexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts); templateconstexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span exts); templateconstexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array& 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); templateconstexpr explicit(*see below*) mdspan(const mdspan& other); constexpr mdspan& operator=(const mdspan& rhs) = default; constexpr mdspan& operator=(mdspan&& rhs) = default; // [[mdspan.mdspan.members]](#members "23.7.3.6.3 Members"), memberstemplateconstexpr reference operator[](OtherIndexTypes... indices) const; templateconstexpr reference operator[](span indices) const; templateconstexpr reference operator[](const array& indices) const; templateconstexpr reference at(OtherIndexTypes... indices) const; // freestanding-deletedtemplateconstexpr reference at(span indices) const; // freestanding-deletedtemplateconstexpr reference at(const array& indices) const; // freestanding-deletedconstexpr 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_*; // *exposition only* mapping_type *map_*; // *exposition only* data_handle_type *ptr_*; // *exposition only*}; templaterequires (is_array_v && rank_v == 1) mdspan(CArray&)-> mdspan, extents>>; templaterequires (is_pointer_v>) mdspan(Pointer&&)-> mdspan>, extents>; templaterequires ((is_convertible_v && ...) && sizeof...(Integrals) > 0)explicit mdspan(ElementType*, Integrals...)-> mdspan synopsis [span.syn]")...>>; template mdspan(ElementType*, span)-> mdspan>; template mdspan(ElementType*, const array&)-> mdspan>; template mdspan(ElementType*, const extents&)-> mdspan>; template mdspan(ElementType*, const MappingType&)-> mdspan; template mdspan(const typename AccessorType::data_handle_type&, const MappingType&, const AccessorType&)-> mdspan;} [2](#overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24772) *Mandates*: - [(2.1)](#overview-2.1) ElementType is a complete object type that is neither an abstract class type nor an array type, - [(2.2)](#overview-2.2) Extents is a specialization of extents, and - [(2.3)](#overview-2.3) is_same_v is true[.](#overview-2.sentence-1) [3](#overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24785) LayoutPolicy shall meet the layout mapping policy requirements ([[mdspan.layout.policy.reqmts]](mdspan.layout.policy.reqmts "23.7.3.4.3 Layout mapping policy requirements")), andAccessorPolicy shall meet the accessor policy requirements ([[mdspan.accessor.reqmts]](mdspan.accessor.reqmts "23.7.3.5.2 Requirements"))[.](#overview-3.sentence-1) [4](#overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24791) Each specialization MDS of mdspan models [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]") and - [(4.1)](#overview-4.1) is_nothrow_move_constructible_v is true, - [(4.2)](#overview-4.2) is_nothrow_move_assignable_v is true, and - [(4.3)](#overview-4.3) is_nothrow_swappable_v is true[.](#overview-4.sentence-1) [5](#overview-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24802) A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_type are trivially copyable types[.](#overview-5.sentence-1) #### [23.7.3.6.2](#cons) Constructors [[mdspan.mdspan.cons]](mdspan.mdspan.cons) [🔗](#lib:mdspan,constructor) `constexpr mdspan(); ` [1](#cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24815) *Constraints*: - [(1.1)](#cons-1.1) rank_dynamic() > 0 is true[.](#cons-1.1.sentence-1) - [(1.2)](#cons-1.2) is_default_constructible_v is true[.](#cons-1.2.sentence-1) - [(1.3)](#cons-1.3) is_default_constructible_v is true[.](#cons-1.3.sentence-1) - [(1.4)](#cons-1.4) is_default_constructible_v is true[.](#cons-1.4.sentence-1) [2](#cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24828) *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[.](#cons-2.sentence-1) [3](#cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24835) *Effects*: Value-initializes *ptr_*, *map_*, and *acc_*[.](#cons-3.sentence-1) [🔗](#lib:mdspan,constructor_) `template constexpr explicit mdspan(data_handle_type p, OtherIndexTypes... exts); ` [4](#cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24847) Let N be sizeof...(OtherIndexTypes)[.](#cons-4.sentence-1) [5](#cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24850) *Constraints*: - [(5.1)](#cons-5.1) (is_convertible_v && ...) is true, - [(5.2)](#cons-5.2) (is_nothrow_constructible && ...) is true, - [(5.3)](#cons-5.3) N == rank() || N == rank_dynamic() is true, - [(5.4)](#cons-5.4) is_constructible_v is true, and - [(5.5)](#cons-5.5) is_default_constructible_v is true[.](#cons-5.sentence-1) [6](#cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24865) *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[.](#cons-6.sentence-1) [7](#cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24872) *Effects*: - [(7.1)](#cons-7.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(7.2)](#cons-7.2) direct-non-list-initializes *map_* withextents_type(static_cast(std​::​move(exts​))...), and - [(7.3)](#cons-7.3) value-initializes *acc_*[.](#cons-7.sentence-1) [🔗](#lib:mdspan,constructor__) `template constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span exts); template constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array& exts); ` [8](#cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24896) *Constraints*: - [(8.1)](#cons-8.1) is_convertible_v is true, - [(8.2)](#cons-8.2) is_nothrow_constructible_v is true, - [(8.3)](#cons-8.3) N == rank() || N == rank_dynamic() is true, - [(8.4)](#cons-8.4) is_constructible_v is true, and - [(8.5)](#cons-8.5) is_default_constructible_v is true[.](#cons-8.sentence-1) [9](#cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24911) *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[.](#cons-9.sentence-1) [10](#cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24918) *Effects*: - [(10.1)](#cons-10.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(10.2)](#cons-10.2) direct-non-list-initializes *map_* with extents_type(exts), and - [(10.3)](#cons-10.3) value-initializes *acc_*[.](#cons-10.sentence-1) [🔗](#lib:mdspan,constructor___) `constexpr mdspan(data_handle_type p, const extents_type& ext); ` [11](#cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24936) *Constraints*: - [(11.1)](#cons-11.1) is_constructible_v is true, and - [(11.2)](#cons-11.2) is_default_constructible_v is true[.](#cons-11.sentence-1) [12](#cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24945) *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[.](#cons-12.sentence-1) [13](#cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24952) *Effects*: - [(13.1)](#cons-13.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(13.2)](#cons-13.2) direct-non-list-initializes *map_* with ext, and - [(13.3)](#cons-13.3) value-initializes *acc_*[.](#cons-13.sentence-1) [🔗](#lib:mdspan,constructor____) `constexpr mdspan(data_handle_type p, const mapping_type& m); ` [14](#cons-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24970) *Constraints*: is_default_constructible_v is true[.](#cons-14.sentence-1) [15](#cons-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24974) *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[.](#cons-15.sentence-1) [16](#cons-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24980) *Effects*: - [(16.1)](#cons-16.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(16.2)](#cons-16.2) direct-non-list-initializes *map_* with m, and - [(16.3)](#cons-16.3) value-initializes *acc_*[.](#cons-16.sentence-1) [🔗](#lib:mdspan,constructor_____) `constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); ` [17](#cons-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24998) *Preconditions*: [0, m.required_span_size()) is an accessible range of p and a[.](#cons-17.sentence-1) [18](#cons-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25003) *Effects*: - [(18.1)](#cons-18.1) Direct-non-list-initializes *ptr_* with std​::​move(p), - [(18.2)](#cons-18.2) direct-non-list-initializes *map_* with m, and - [(18.3)](#cons-18.3) direct-non-list-initializes *acc_* with a[.](#cons-18.sentence-1) [🔗](#lib:mdspan,constructor______) `template constexpr explicit(see below) mdspan(const mdspan& other); ` [19](#cons-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25025) *Constraints*: - [(19.1)](#cons-19.1) is_constructible_v&> is true, and - [(19.2)](#cons-19.2) is_constructible_v is true[.](#cons-19.sentence-1) [20](#cons-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25035) *Mandates*: - [(20.1)](#cons-20.1) is_constructible_v is true, and - [(20.2)](#cons-20.2) is_constructible_v is true[.](#cons-20.sentence-1) [21](#cons-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25044) *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[.](#cons-21.sentence-1) [22](#cons-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25051) *Hardened preconditions*: For each rank index r of extents_type,static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r) is true[.](#cons-22.sentence-1) [23](#cons-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25057) *Effects*: - [(23.1)](#cons-23.1) Direct-non-list-initializes *ptr_* with other.*ptr_*, - [(23.2)](#cons-23.2) direct-non-list-initializes *map_* with other.*map_*, and - [(23.3)](#cons-23.3) direct-non-list-initializes *acc_* with other.*acc_*[.](#cons-23.sentence-1) [24](#cons-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25068) *Remarks*: The expression inside explicit is equivalent to:!is_convertible_v&, mapping_type>|| !is_convertible_v #### [23.7.3.6.3](#members) Members [[mdspan.mdspan.members]](mdspan.mdspan.members) [🔗](#lib:operator%5b%5d,mdspan) `template constexpr reference operator[](OtherIndexTypes... indices) const; ` [1](#members-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25086) *Constraints*: - [(1.1)](#members-1.1) (is_convertible_v && ...) is true, - [(1.2)](#members-1.2) (is_nothrow_constructible_v && ...) is true, and - [(1.3)](#members-1.3) sizeof...(OtherIndexTypes) == rank() is true[.](#members-1.sentence-1) [2](#members-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25097) Let I be extents_type​::​*index-cast*(std​::​move(indices))[.](#members-2.sentence-1) [3](#members-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25100) *Hardened preconditions*: I is a multidimensional index in extents()[.](#members-3.sentence-1) [*Note [1](#members-note-1)*: This implies that*map_*(I) < *map_*.required_span_size() is true[.](#members-3.sentence-2) — *end note*] [4](#members-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25109) *Effects*: Equivalent to:return *acc_*.access(*ptr_*, *map_*(static_cast(std::move(indices))...)); [🔗](#lib:operator%5b%5d,mdspan_) `template constexpr reference operator[](span indices) const; template constexpr reference operator[](const array& indices) const; ` [5](#members-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25126) *Constraints*: - [(5.1)](#members-5.1) is_convertible_v is true, and - [(5.2)](#members-5.2) is_nothrow_constructible_v is true[.](#members-5.sentence-1) [6](#members-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25135) *Effects*: Let P be a parameter pack such thatis_same_v, index_sequence> is true[.](#members-6.sentence-1) Equivalent to:return operator[](extents_type::*index-cast*(as_const(indices[P]))...); [🔗](#lib:at,mdspan) `template constexpr reference at(OtherIndexTypes... indices) const; ` [7](#members-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25155) *Constraints*: - [(7.1)](#members-7.1) (is_convertible_v && ...) is true, - [(7.2)](#members-7.2) (is_nothrow_constructible_v && ...) is true, and - [(7.3)](#members-7.3) sizeof...(OtherIndexTypes) == rank() is true[.](#members-7.sentence-1) [8](#members-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25166) Let I be extents_type​::​*index-cast*(std​::​move(indices))[.](#members-8.sentence-1) [9](#members-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25169) *Returns*: (*this)[I...][.](#members-9.sentence-1) [10](#members-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25173) *Throws*: out_of_range if I is not a multidimensional index in extents()[.](#members-10.sentence-1) [🔗](#lib:at,mdspan_) `template constexpr reference at(span indices) const; template constexpr reference at(const array& indices) const; ` [11](#members-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25187) *Constraints*: - [(11.1)](#members-11.1) is_convertible_v is true, and - [(11.2)](#members-11.2) is_nothrow_constructible_v is true[.](#members-11.sentence-1) [12](#members-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25196) *Effects*: Let P be a parameter pack such thatis_same_v, index_sequence> is true[.](#members-12.sentence-1) Equivalent to:return at(extents_type::*index-cast*(as_const(indices[P]))...); [🔗](#lib:size,mdspan) `constexpr size_type size() const noexcept; ` [13](#members-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25215) *Preconditions*: The size of the multidimensional index space extents() is representable as a value of type size_type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#members-13.sentence-1) [14](#members-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25220) *Returns*: extents().*fwd-prod-of-extents*(rank())[.](#members-14.sentence-1) [🔗](#lib:empty,mdspan) `constexpr bool empty() const noexcept; ` [15](#members-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25231) *Returns*: true if the size of the multidimensional index space extents() is 0, otherwise false[.](#members-15.sentence-1) [🔗](#lib:swap,mdspan) `friend constexpr void swap(mdspan& x, mdspan& y) noexcept; ` [16](#members-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25244) *Effects*: Equivalent to:swap(x.*ptr_*, y.*ptr_*); swap(x.*map_*, y.*map_*); swap(x.*acc_*, y.*acc_*);