Files
2025-10-25 03:02:53 +03:00

455 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.7Views"),extents is used synonymously with multidimensional index space[.](#overview-sentence-2)
namespace std {template<class IndexType, size_t... Extents>class [extents](#lib:extents "23.7.3.3.1Overview[mdspan.extents.overview]") {public:using index_type = IndexType; using size_type = make_unsigned_t<index_type>; using rank_type = size_t; // [[mdspan.extents.obs]](#obs "23.7.3.3.4Observers 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.3Constructors"), constructorsconstexpr 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; // [[mdspan.extents.cmp]](#cmp "23.7.3.3.5Comparison operators"), comparison operatorstemplate<class OtherIndexType, size_t... OtherExtents>friend constexpr bool operator==(const extents&, const extents<OtherIndexType, OtherExtents...>&) noexcept; // [[mdspan.extents.expo]](#expo "23.7.3.3.2Exposition-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*template<class OtherIndexType>static 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<index_type, rank_dynamic()> *dynamic-extents*{}; // *exposition only*}; template<class... Integrals>explicit 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.6Object 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.1Overview[mdspan.extents.overview]") if it is equal to dynamic_extent,
otherwise Er is a [*static extent*](#def:extent,static "23.7.3.3.1Overview[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<i for which Er is a dynamic extent[.](#expo-2.sentence-1)
[🔗](#expo-itemdecl:2)
`static constexpr rank_type dynamic-index-inv(rank_type i) noexcept;
`
[3](#expo-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21199)
*Preconditions*: i < rank_dynamic() is true[.](#expo-3.sentence-1)
[4](#expo-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21203)
*Returns*: The minimum value of r such that *dynamic-index*(r + 1) == i + 1 is true[.](#expo-4.sentence-1)
[🔗](#expo-itemdecl:3)
`constexpr size_t fwd-prod-of-extents(rank_type i) const noexcept;
`
[5](#expo-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21214)
*Preconditions*: i <= rank() is true[.](#expo-5.sentence-1)
[6](#expo-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21218)
*Returns*: If i > 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<class OtherIndexType>
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<index_type>(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<class OtherIndexType, size_t... OtherExtents>
constexpr explicit(see below)
extents(const extents<OtherIndexType, OtherExtents...>& 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<index_type>::max() < numeric_limits<OtherIndexType>::max())
[🔗](#lib:extents,constructor_)
`template<class... OtherIndexTypes>
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<index_type, N>{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<OtherIndexTypes, index_type> && ...) is true,
- [(6.2)](#cons-6.2)
(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) 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<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;
`
[9](#cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21377)
*Constraints*:
- [(9.1)](#cons-9.1)
is_convertible_v<const OtherIndexType&, index_type> is true,
- [(9.2)](#cons-9.2)
is_nothrow_constructible_v<index_type, const OtherIndexType&> 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<class... Integrals>
explicit extents(Integrals...) -> see below;
`
[12](#cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L21427)
*Constraints*: (is_convertible_v<Integrals, size_t> && ...) 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<size_t, [*maybe-static-ext*](span.syn#concept:maybe-static-ext "23.7.2.1Header <span> synopsis[span.syn]")<Integrals>...>[.](#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<class OtherIndexType, size_t... OtherExtents>
friend constexpr bool operator==(const extents& lhs,
const extents<OtherIndexType, OtherExtents...>& 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<class IndexType, size_t Rank>
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<size_t Rank, class IndexType = size_t>
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)