[mdspan.extents] # 23 Containers library [[containers]](./#containers) ## 23.7 Views [[views]](views#mdspan.extents) ### 23.7.3 Multidimensional access [[views.multidim]](views.multidim#mdspan.extents) #### 23.7.3.3 Class template extents [mdspan.extents] #### [23.7.3.3.1](#overview) Overview [[mdspan.extents.overview]](mdspan.extents.overview) The class template extents represents a multidimensional index space of rank equal to sizeof...(Extents)[.](#overview-sentence-1) In [[views]](views "23.7 Views"),extents is used synonymously with multidimensional index space[.](#overview-sentence-2) namespace std {templateclass [extents](#lib:extents "23.7.3.3.1 Overview [mdspan.extents.overview]") {public:using index_type = IndexType; using size_type = make_unsigned_t; using rank_type = size_t; // [[mdspan.extents.obs]](#obs "23.7.3.3.4 Observers of the multidimensional index space"), observers of the multidimensional index spacestatic 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; // [[mdspan.extents.cons]](#cons "23.7.3.3.3 Constructors"), constructorsconstexpr extents() noexcept = default; templateconstexpr explicit(*see below*) extents(const extents&) noexcept; templateconstexpr explicit extents(OtherIndexTypes...) noexcept; templateconstexpr explicit(N != rank_dynamic()) extents(span) noexcept; templateconstexpr explicit(N != rank_dynamic()) extents(const array&) noexcept; // [[mdspan.extents.cmp]](#cmp "23.7.3.3.5 Comparison operators"), comparison operatorstemplatefriend constexpr bool operator==(const extents&, const extents&) noexcept; // [[mdspan.extents.expo]](#expo "23.7.3.3.2 Exposition-only helpers"), exposition-only helpersconstexpr size_t *fwd-prod-of-extents*(rank_type) const noexcept; // *exposition only*constexpr size_t *rev-prod-of-extents*(rank_type) const noexcept; // *exposition only*templatestatic constexpr auto *index-cast*(OtherIndexType&&) noexcept; // *exposition only*private:static constexpr rank_type *dynamic-index*(rank_type) noexcept; // *exposition only*static constexpr rank_type *dynamic-index-inv*(rank_type) noexcept; // *exposition only* array *dynamic-extents*{}; // *exposition only*}; templateexplicit extents(Integrals...)-> *see below*;} [1](#overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21152) *Mandates*: - [(1.1)](#overview-1.1) IndexType is a signed or unsigned integer type, and - [(1.2)](#overview-1.2) each element of Extents is either equal to dynamic_extent, or is representable as a value of type IndexType[.](#overview-1.sentence-1) [2](#overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21162) Each specialization of extents models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") and is trivially copyable[.](#overview-2.sentence-1) [3](#overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21166) Let Er be the rth element of Extents[.](#overview-3.sentence-1) Er is a [*dynamic extent*](#def:extent,dynamic "23.7.3.3.1 Overview [mdspan.extents.overview]") if it is equal to dynamic_extent, otherwise Er is a [*static extent*](#def:extent,static "23.7.3.3.1 Overview [mdspan.extents.overview]")[.](#overview-3.sentence-2) Let Dr be the value of *dynamic-extents*[*dynamic-index*(r)] if Er is a dynamic extent, otherwise Er[.](#overview-3.sentence-3) [4](#overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21174) The rth interval of the multidimensional index space represented by an extents object is [0,Dr)[.](#overview-4.sentence-1) #### [23.7.3.3.2](#expo) Exposition-only helpers [[mdspan.extents.expo]](mdspan.extents.expo) [🔗](#expo-itemdecl:1) `static constexpr rank_type dynamic-index(rank_type i) noexcept; ` [1](#expo-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21185) *Preconditions*: i <= rank() is true[.](#expo-1.sentence-1) [2](#expo-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21189) *Returns*: The number of Er with r 0 is true, the product of extent(k) for all k in the range [0, i), otherwise 1[.](#expo-6.sentence-1) [🔗](#expo-itemdecl:4) `constexpr size_t rev-prod-of-extents(rank_type i) const noexcept; ` [7](#expo-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21230) *Preconditions*: i < rank() is true[.](#expo-7.sentence-1) [8](#expo-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21234) *Returns*: If i + 1 < rank() is true, the product of extent(k) for all k in the range [i + 1, rank()), otherwise 1[.](#expo-8.sentence-1) [🔗](#expo-itemdecl:5) `template static constexpr auto index-cast(OtherIndexType&& i) noexcept; ` [9](#expo-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21248) *Effects*: - [(9.1)](#expo-9.1) If OtherIndexType is an integral type other than bool, then equivalent to return i;, - [(9.2)](#expo-9.2) otherwise, equivalent to return static_cast(i);[.](#expo-9.sentence-1) [*Note [1](#expo-note-1)*: This function will always return an integral type other than bool[.](#expo-9.sentence-2) 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[.](#expo-9.sentence-3) — *end note*] #### [23.7.3.3.3](#cons) Constructors [[mdspan.extents.cons]](mdspan.extents.cons) [🔗](#lib:extents,constructor) `template constexpr explicit(see below) extents(const extents& other) noexcept; ` [1](#cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21276) *Constraints*: - [(1.1)](#cons-1.1) sizeof...(OtherExtents) == rank() is true[.](#cons-1.1.sentence-1) - [(1.2)](#cons-1.2) ((OtherExtents == dynamic_extent || Extents == dynamic_extent || OtherExtents == Extents) && ...) is true[.](#cons-1.2.sentence-1) [2](#cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21285) *Preconditions*: - [(2.1)](#cons-2.1) other.extent(r) equals Er for each r for which Er is a static extent, and - [(2.2)](#cons-2.2) either * [(2.2.1)](#cons-2.2.1) sizeof...(OtherExtents) is zero, or * [(2.2.2)](#cons-2.2.2) other.extent(r) is representable as a value of type index_type for every rank index r of other[.](#cons-2.sentence-1) [3](#cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21302) *Postconditions*: *this == other is true[.](#cons-3.sentence-1) [4](#cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21306) *Remarks*: The expression inside explicit is equivalent to:(((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) ||(numeric_limits::max() < numeric_limits::max()) [🔗](#lib:extents,constructor_) `template constexpr explicit extents(OtherIndexTypes... exts) noexcept; ` [5](#cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21322) Let N be sizeof...(OtherIndexTypes), and let exts_arr bearray{static_cast< index_type>(std​::​move(exts))...}[.](#cons-5.sentence-1) [6](#cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21327) *Constraints*: - [(6.1)](#cons-6.1) (is_convertible_v && ...) is true, - [(6.2)](#cons-6.2) (is_nothrow_constructible_v && ...) is true, and - [(6.3)](#cons-6.3) N == rank_dynamic() || N == rank() is true[.](#cons-6.sentence-1) [*Note [1](#cons-note-1)*: One can construct extents from just dynamic extents, which are all the values getting stored, or from all the extents with a precondition[.](#cons-6.3.sentence-2) — *end note*] [7](#cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21343) *Preconditions*: - [(7.1)](#cons-7.1) If N != rank_dynamic() is true,exts_arr[r] equals Er for each r for which Er is a static extent, and - [(7.2)](#cons-7.2) either * [(7.2.1)](#cons-7.2.1) sizeof...(exts) == 0 is true, or * [(7.2.2)](#cons-7.2.2) each element of exts is representable as a nonnegative value of type index_type[.](#cons-7.sentence-1) [8](#cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21361) *Postconditions*: *this == extents(exts_arr) is true[.](#cons-8.sentence-1) [🔗](#lib:extents,constructor__) `template constexpr explicit(N != rank_dynamic()) extents(span exts) noexcept; template constexpr explicit(N != rank_dynamic()) extents(const array& exts) noexcept; ` [9](#cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21377) *Constraints*: - [(9.1)](#cons-9.1) is_convertible_v is true, - [(9.2)](#cons-9.2) is_nothrow_constructible_v is true, and - [(9.3)](#cons-9.3) N == rank_dynamic() || N == rank() is true[.](#cons-9.sentence-1) [10](#cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21388) *Preconditions*: - [(10.1)](#cons-10.1) If N != rank_dynamic() is true,exts[r] equals Er for each r for which Er is a static extent, and - [(10.2)](#cons-10.2) either * [(10.2.1)](#cons-10.2.1) N is zero, or * [(10.2.2)](#cons-10.2.2) exts[r] is representable as a nonnegative value of type index_type for every rank index r[.](#cons-10.sentence-1) [11](#cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21405) *Effects*: - [(11.1)](#cons-11.1) If N equals rank_dynamic(), for all d in the range [0, rank_dynamic()), direct-non-list-initializes *dynamic-extents*[d] with as_const(exts[d])[.](#cons-11.1.sentence-1) - [(11.2)](#cons-11.2) Otherwise, for all d in the range [0, rank_dynamic()), direct-non-list-initializes *dynamic-extents*[d] with as_const(exts[*dynamic-index-inv*(d)])[.](#cons-11.2.sentence-1) [🔗](#lib:extents,constructor___) `template explicit extents(Integrals...) -> see below; ` [12](#cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21427) *Constraints*: (is_convertible_v && ...) is true[.](#cons-12.sentence-1) [13](#cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21431) *Remarks*: The deduced type is extents synopsis [span.syn]")...>[.](#cons-13.sentence-1) #### [23.7.3.3.4](#obs) Observers of the multidimensional index space [[mdspan.extents.obs]](mdspan.extents.obs) [🔗](#lib:static_extent,extents) `static constexpr size_t static_extent(rank_type i) noexcept; ` [1](#obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21444) *Preconditions*: i < rank() is true[.](#obs-1.sentence-1) [2](#obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21448) *Returns*: Ei[.](#obs-2.sentence-1) [🔗](#lib:extent,extents) `constexpr index_type extent(rank_type i) const noexcept; ` [3](#obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21459) *Preconditions*: i < rank() is true[.](#obs-3.sentence-1) [4](#obs-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21463) *Returns*: Di[.](#obs-4.sentence-1) #### [23.7.3.3.5](#cmp) Comparison operators [[mdspan.extents.cmp]](mdspan.extents.cmp) [🔗](#lib:operator==,extents) `template friend constexpr bool operator==(const extents& lhs, const extents& rhs) noexcept; ` [1](#cmp-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21478) *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[.](#cmp-1.sentence-1) #### [23.7.3.3.6](#dextents) Alias template dextents [[mdspan.extents.dextents]](mdspan.extents.dextents) [🔗](#lib:dextents) `template using dextents = see below; ` [1](#dextents-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21495) *Result*: A type E that is a specialization of extents such that E​::​rank() == Rank && E​::​rank() == E​::​rank_dynamic() is true, andE​::​index_type denotes IndexType[.](#dextents-1.sentence-1) #### [23.7.3.3.7](#dims) Alias template dims [[mdspan.extents.dims]](mdspan.extents.dims) [🔗](#lib:dims) `template using dims = see below; ` [1](#dims-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21511) *Result*: A type E that is a specialization of extents such that E​::​rank() == Rank && E​::​rank() == E​::​rank_dynamic() is true, andE​::​index_type denotes IndexType[.](#dims-1.sentence-1)