455 lines
16 KiB
Markdown
455 lines
16 KiB
Markdown
[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 {template<class IndexType, size_t... Extents>class [extents](#lib:extents "23.7.3.3.1 Overview [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.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; 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.5 Comparison 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.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*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.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<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.1 Header <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)
|