M denotes a layout mapping class
. m denotes a (possibly const) value of type
M. i and
j are packs of (possibly const) integers
that are multidimensional indices in
m.extents() (
[mdspan.overview])
. [
Note 1:
The type of each element of the packs can be a different integer type
. —
end note]
r is a (possibly const) rank index of
typename M::extents_type. dr is a pack of (possibly const) integers
for which
sizeof...(dr) == M::extents_type::rank() is
true,
the
rth element is equal to 1, and
all other elements are equal to 0
.
In
[mdspan.layout.reqmts] through
[mdspan.layout.stride]:
- Let is-mapping-of be the exposition-only variable template defined as follows:
template<class Layout, class Mapping>
constexpr bool is-mapping-of =
is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
- Let is-layout-left-padded-mapping-of be
the exposition-only variable template defined as follows:
template<class Mapping>
constexpr bool is-layout-left-padded-mapping-of = see below;
where is-layout-left-padded-mapping-of<Mapping> is true
if and only if Mapping denotes
a specialization of layout_left_padded<S>::mapping
for some value S of type size_t.
- Let is-layout-right-padded-mapping-of be
the exposition-only variable template defined as follows:
template<class Mapping>
constexpr bool is-layout-right-padded-mapping-of = see below;
where is-layout-right-padded-mapping-of<Mapping> is true
if and only if Mapping denotes
a specialization of layout_right_padded<S>::mapping
for some value S of type size_t.
- For nonnegative integers x and y,
let LEAST-MULTIPLE-AT-LEAST(x,y) denote
- y if x is zero,
- otherwise, the least multiple of x that is greater than or equal to y.
- M models copyable and equality_comparable,
- is_nothrow_move_constructible_v<M> is true,
- is_nothrow_move_assignable_v<M> is true,
- is_nothrow_swappable_v<M> is true, and
- the following types and expressions are well-formed and
have the specified semantics.
Result: A type that is a specialization of
extents. Result:
typename M::extents_type::index_type. Result:
typename M::extents_type::rank_type. 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
sr
such that,
for all
i where
(i+dr) is
a multidimensional index in
m.extents() (
[mdspan.overview]),
m((i + dr)...) - m(i...) equals
sr. [
Note 3:
This implies that for a strided layout
m(i0,…,ik)=m(0,…,0)+i0×s0+⋯+ik×sk. —
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:
sr 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
true
for 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
true
for 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
true
for 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]
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
X
that 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.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 of
layout_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
true
for any such type
T.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(extents_type::rank() > 0)
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. 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_right::mapping<OtherExtents>& other) noexcept;
Constraints:
- extents_type::rank() <= 1 is true, and
- 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 LayoutLeftPaddedMapping>
constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
extents_type>)
mapping(const LayoutLeftPaddedMapping&) noexcept;
Constraints:
is-layout-left-padded-mapping-of<LayoutLeftPaddedMapping> is
true. is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>is
true.
Mandates: If
- Extents::rank() is greater than one,
- Extents::static_extent(0) does not equal dynamic_extent, and
- LayoutLeftPaddedMapping::static-padding-stride
does not equal dynamic_extent,
then
Extents::static_extent(0) equals
LayoutLeftPaddedMapping::static-padding-stride. Preconditions:
If
extents_type::rank() > 1 is
true,
then
other.stride(1) equals
other.extents(0).other.required_span_size() is representable as
a value of type
index_type.
Effects: Direct-non-list-initializes
extents_ with
other.extents(). template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0)
mapping(const layout_stride::mapping<OtherExtents>& other);
Constraints:
is_constructible_v<extents_type, OtherExtents> is
true. Preconditions:
- If extents_type::rank() > 0 is true,
then for all r in the range [0, extents_type::rank()),
other.stride(r) equals
other.extents().fwd-prod-of-extents(r), and
- other.required_span_size() is representable as
a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes
extents_ with
other.extents(). 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:
- sizeof...(Indices) == extents_type::rank() is true,
- (is_convertible_v<Indices, index_type> && ...) is true, and
- (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
Preconditions:
extents_type::index-cast(i) is
a multidimensional index in
extents_ (
[mdspan.overview])
. Effects: Let
P be a parameter pack such that
is_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();
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(extents_type::rank() > 0)
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. 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:
- extents_type::rank() <= 1 is true, and
- 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 LayoutRightPaddedMapping>
constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
extents_type>)
mapping(const LayoutRightPaddedMapping&) noexcept;
Constraints:
is-layout-right-padded-mapping-of<LayoutRightPaddedMapping>
is
true. is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type>
is
true.
Mandates: If
- Extents::rank() is greater than one,
- Extents::static_extent(Extents::rank() - 1)
does not equal dynamic_extent, and
- LayoutRightPaddedMapping::static-padding-stride
does not equal dynamic_extent,
then
Extents::static_extent(Extents::rank() - 1) equals
LayoutRightPaddedMapping::static-padding-stride. Preconditions:
If
extents_type::rank() > 1 is
true,
then
other.stride(extents_type::rank() - 2)equals
other.extents().extent(extents_type::rank() - 1).other.required_span_size() is representable as
a value of type
index_type.
Effects: Direct-non-list-initializes
extents_ with
other.extents(). template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0)
mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
Constraints:
is_constructible_v<extents_type, OtherExtents> is
true. Preconditions:
If
extents_type::rank() > 0 is
true,
then for all
r in the range
[0, extents_type::rank()),
other.stride(r) equals
other.extents().rev-prod-of-extents(r).
Effects: Direct-non-list-initializes
extents_ with
other.extents(). 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:
- sizeof...(Indices) == extents_type::rank() is true,
- (is_convertible_v<Indices, index_type> && ...) is true, and
- (is_nothrow_constructible_v<index_type, Indices> && ...) is
true.
Preconditions:
extents_type::index-cast(i) is
a multidimensional index in
extents_ (
[mdspan.overview])
. Effects: Let
P be a parameter pack such that
is_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();
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 { return false; }
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. Let
REQUIRED-SPAN-SIZE(e, strides) be:
- 1, if e.rank() == 0 is true,
- otherwise 0, if the size of the multidimensional index space e is 0,
- otherwise 1 plus the sum of products of
(e.extent(r) - 1) and
extents_type::index-cast(strides[r])
for all r in the range [0, e.rank()).
Let
OFFSET(m) be:
- m(), if e.rank() == 0 is true,
- otherwise 0, if the size of the multidimensional index space e is 0,
- otherwise m(z...) for a pack of integers z
that is a multidimensional index in m.extents() and
each element of z equals 0.
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 functions
M::is_always_strided(),
M::is_always_exhaustive(), and
M::is_always_unique() exist,
are constant expressions, and
have a return type of
bool. —
end note]
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] with
layout_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:
- is_convertible_v<const OtherIndexType&, index_type> is true, and
- is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
Preconditions:
The result of converting
s[i] to
index_type
is greater than
0
for all
i in the range
[0, rank_).If
rank_ is greater than 0,
then there exists a permutation
P of the integers
in the range
[0, rank_),
such that
s[pi] >= s[pi−1] * e.extent(pi−1) is
true
for all
i in the range
[1, rank_),
where
pi is the
ith element of
P. [
Note 1:
For
layout_stride,
this condition is necessary and sufficient
for
is_unique() to be
true. —
end note]
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:
is_constructible_v<extents_type, typename StridedLayoutMapping::extents_type> is
StridedLayoutMapping::is_always_unique() is
true. StridedLayoutMapping::is_always_strided() is
true.
Preconditions:
- StridedLayoutMapping meets the layout mapping requirements ([mdspan.layout.reqmts]),
- other.stride(r) > 0 is true
for every rank index r of extents(),
- other.required_span_size() is representable as
a value of type index_type ([basic.fundamental]), and
- OFFSET(other) == 0 is true.
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>))
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:
- sizeof...(Indices) == rank_ is true,
- (is_convertible_v<Indices, index_type> && ...) is true, and
- (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
Preconditions:
extents_type::index-cast(i) is
a multidimensional index in
extents_ (
[mdspan.overview])
. Effects: Let
P be a parameter pack such that
is_same_v<index_sequence_for<Indices...>, index_sequence<P...>>
is
true. Equivalent to:
return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
constexpr bool is_exhaustive() const noexcept;
Returns:
Otherwise,
true if there is
a permutation
P of the integers in the range
[0, rank_)
such that
stride(p0) equals 1, and
stride(pi) equals
stride(pi−1) * extents().extent(pi−1)
for
i in the range
[1, rank_),
where
pi is the
ith element of
P.
template<class OtherMapping>
friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept;
Constraints:
rank_ == OtherMapping::extents_type::rank() is
true. OtherMapping::is_always_strided() is
true.
Returns:
true if
x.extents() == y.extents() is
true,
OFFSET(y) == 0 is
true, and
each of
x.stride(r) == y.stride(r) is
true
for
r in the range
[0, x.extents().rank()). 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(extents_type::rank() > 0)
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:
- the empty parameter pack, if rank_ equals zero;
- otherwise, 0zu, if rank_ equals one;
- otherwise, the parameter pack 0zu, 1zu, …, rank_- 1.
Mandates:
If
rank_dynamic() == 0 is
true,
then the size of the multidimensional index space
Extents()
is representable as a value of type
index_type.padding_value is representable as a value of type
index_type. If
- rank_ is greater than one,
- padding_value does not equal dynamic_extent, and
- first-static-extent does not equal dynamic_extent,
then
LEAST-MULTIPLE-AT-LEAST(padding_value, first-static-extent)
is representable as a value of type
size_t, and
is representable as a value of type
index_type.If
- rank_ is greater than one,
- padding_value does not equal dynamic_extent, and
- extents_type::static_extent(k) does not equal dynamic_extent
for all k in the range [0, extents_type::rank()),
then the product of
LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(0)) and
all values
ext.static_extent(k)
with
k in the range of [
1, rank_)
is representable as a value of type
size_t, and
is representable as a value of type
index_type.
static constexpr size_t static-padding-stride = see below;
The value is
- 0, if rank_ equals zero or one;
- otherwise, dynamic_extent,
if padding_value or first-static-extent equals
dynamic_extent;
- otherwise, the size_t value which is
LEAST-MULTIPLE-AT-LEAST(padding_value, first-static-extent).
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 of
index_type as the type of
stride-1 would achieve this
. —
end note]
constexpr mapping(const extents_type& ext);
Preconditions:
The size of the multidimensional index space
ext is representable as
a value of type
index_type.If
rank_ is greater than one and
padding_value does not equal
dynamic_extent,
then
LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(0))
is representable as a value of type
index_type.If
rank_ is greater than one and
padding_value does not equal
dynamic_extent,
then the product of
LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(0)) and
all values
ext.extent(k)
with
k in the range of [
1, rank_)
is representable as a value of type
index_type.
Effects:
- Direct-non-list-initializes extents_ with ext; and
- if rank_ is greater than one,
direct-non-list-initializes stride-1
- with ext.extent(0) if padding_value is dynamic_extent,
- otherwise with
LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(0)).
template<class OtherIndexType>
constexpr mapping(const extents_type& ext, OtherIndexType pad);
Constraints:
is_convertible_v<OtherIndexType, index_type> is
true. is_nothrow_constructible_v<index_type, OtherIndexType> is
true.
Preconditions:
pad is representable as a value of type
index_type. extents_type::index-cast(pad) is greater than zero
. If rank_ is greater than one,
then LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(0))
is representable as a value of type index_type.
If
rank_ is greater than one,
then the product of
LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(0)) and
all values
ext.extent(k)
with
k in the range of [
1, rank_)
is representable as a value of type
index_type.If
padding_value is not equal to
dynamic_extent,
padding_value equals
extents_type::index-cast(pad).
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:
- If extents_type::rank() > 1 is true and
padding_value == dynamic_extent is false,
then other.stride(1) equals
LEAST-MULTIPLE-AT-LEAST(padding_value,
extents_type::index-cast(other.extents().extent(0)))
and
- other.required_span_size() is representable as
a value of type index_type.
Effects: Equivalent to
mapping(other.extents()). template<class OtherExtents>
constexpr explicit(rank_ > 0)
mapping(const layout_stride::mapping<OtherExtents>& other);
Constraints:
is_constructible_v<extents_type, OtherExtents> is
true. Preconditions:
If rank_ is greater than 1 and
padding_value does not equal dynamic_extent,
then other.stride(1) equals
LEAST-MULTIPLE-AT-LEAST(padding_value,
extents_type::index-cast(other.extents().extent(0)))
If
rank_ is greater than 0,
then
other.stride(0) equals 1
.If rank_ is greater than 2,
then for all r in the range [2, rank_),
other.stride(r) equals
(other.extents().fwd-prod-of-extents(r) / other.extents().extent(0)) * other.stride(1)
other.required_span_size() is representable as
a value of type
index_type.
Effects:
- Direct-non-list-initializes extents_ with other.extents() and
- if rank_ is greater than one,
direct-non-list-initializes stride-1 with
other.stride(1).
template<class LayoutLeftPaddedMapping>
constexpr explicit(see below)
mapping(const LayoutLeftPaddedMapping& other);
Constraints:
is-layout-left-padded-mapping-of<LayoutLeftPaddedMapping>
is
true. is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>
is
true.
Mandates: If
rank_ is greater than 1,
then
padding_value == dynamic_extent ||
LayoutLeftPaddedMapping::padding_value == dynamic_extent ||
padding_value == LayoutLeftPaddedMapping::padding_value
is
true. Preconditions:
- If rank_ is greater than 1 and
padding_value does not equal dynamic_extent,
then other.stride(1) equals
LEAST-MULTIPLE-AT-LEAST(padding_value,
extents_type::index-cast(other.extent(0)))
- other.required_span_size() is representable as
a value of type index_type.
Effects:
- Direct-non-list-initializes extents_ with other.extents() and
- if rank_ is greater than one,
direct-non-list-initializes stride-1 with other.stride(1).
Remarks: The expression inside explicit is equivalent to:
rank_> 1 &&
(padding_value != dynamic_extent ||
LayoutLeftPaddedMapping::padding_value == dynamic_extent)
template<class LayoutRightPaddedMapping>
constexpr explicit(see below)
mapping(const LayoutRightPaddedMapping& other) noexcept;
Constraints:
is-layout-right-padded-mapping-of<LayoutRightPaddedMapping>
is
true or
is-mapping-of<layout_right, LayoutRightPaddedMapping>
is
true. rank_ equals zero or one
. is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type>
is
true.
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]
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:
sizeof...(Indices) == rank_ is
true. (is_convertible_v<Indices, index_type> && ...) is
true. (is_nothrow_constructible_v<index_type, Indices> && ...) is
true.
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:
- If rank_ equals zero or one, then true;
- otherwise, if
neither static-padding-stride nor first-static-extent
equal dynamic_extent,
then static-padding-stride == first-static-extent;
- otherwise, false.
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:
- If r equals zero: 1;
- otherwise, if r equals one: stride-1;
- otherwise, the product of stride-1 and
all values extents_.extent(k) with k in the range [1, r).
template<class LayoutLeftPaddedMapping>
friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;
Constraints:
is-layout-left-padded-mapping-of<LayoutLeftPaddedMapping>
is
true. LayoutLeftPaddedMapping::extents_type::rank() == rank_ is
true.
Returns:
true if
x.extents() == y.extents() is
true and
rank_ < 2 || x.stride(1) == y.
stride(1) is
true. 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 to
extents_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(rank_ > 0)
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:
- the empty parameter pack, if rank_ equals zero;
- otherwise, 0zu, if rank_ equals one;
- otherwise, the parameter pack 0zu, 1zu, …, rank_- 1.
Mandates:
If
rank_dynamic() == 0 is
true,
then the size of the multidimensional index space
Extents()
is representable as a value of type
index_type.padding_value is representable as a value of type
index_type. If
- rank_ is greater than one,
- padding_value does not equal dynamic_extent, and
- last-static-extent does not equal dynamic_extent,
then
LEAST-MULTIPLE-AT-LEAST(padding_value, last-static-extent)
is representable as a value of type
size_t, and
is representable as a value of type
index_type.If
- rank_ is greater than one,
- padding_value does not equal dynamic_extent, and
- extents_type::static_extent(k) does not equal dynamic_extent
for all k in the range [0, rank_),
then the product of
LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(rank_ - 1)) and
all values
ext.static_extent(k)
with
k in the range of [
0, rank_ - 1)
is representable as a value of type
size_t, and
is representable as a value of type
index_type.
static constexpr size_t static-padding-stride = see below;
The value is
- 0, if rank_ equals zero or one;
- otherwise, dynamic_extent,
if padding_value or last-static-extent equals
dynamic_extent;
- otherwise, the size_t value which is
LEAST-MULTIPLE-AT-LEAST(padding_value, last-static-extent).
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]
constexpr mapping(const extents_type& ext);
Preconditions:
The size of the multidimensional index space
ext
is representable as a value of type
index_type.If
rank_ is greater than one and
padding_value does not equal
dynamic_extent,
then
LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(rank_ - 1))
is representable as a value of type
index_type.If
rank_ is greater than one and
padding_value does not equal
dynamic_extent,
then the product of
LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(rank_ - 1)) and
all values
ext.extent(k)
with
k in the range of [
0, rank_ - 1)
is representable as a value of type
index_type.
Effects:
- Direct-non-list-initializes extents_ with ext; and
- if rank_ is greater than one,
direct-non-list-initializes stride-rm2
- with ext.extent(rank_ - 1)
if padding_value is dynamic_extent,
- otherwise with
LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(rank_ - 1)).
template<class OtherIndexType>
constexpr mapping(const extents_type& ext, OtherIndexType pad);
Constraints:
is_convertible_v<OtherIndexType, index_type> is
true. is_nothrow_constructible_v<index_type, OtherIndexType> is
true.
Preconditions:
pad is representable as a value of type
index_type. extents_type::index-cast(pad) is greater than zero
. If
rank_ is greater than one,
then
LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(rank_ - 1))
is representable as a value of type
index_type.If
rank_ is greater than one,
then the product of
LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(rank_ - 1)) and
all values
ext.extent(k)
with
k in the range of [
0, rank_ - 1)
is representable as a value of type
index_type.If
padding_value is not equal to
dynamic_extent,
padding_value equals
extents_type::index-cast(pad).
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:
- If rank_ > 1 is true and
padding_value == dynamic_extent is false, then
other.stride(
rank_ - 2) equals
LEAST-MULTIPLE-AT-LEAST(padding_value,
extents_type::index-cast(other.extents().extent(rank_ - 1)))
and - other.required_span_size() is representable as
a value of type index_type.
Effects: Equivalent to
mapping(other.extents()). template<class OtherExtents>
constexpr explicit(rank_ > 0)
mapping(const layout_stride::mapping<OtherExtents>& other);
Constraints:
is_constructible_v<extents_type, OtherExtents> is
true. Preconditions:
If rank_ is greater than 1 and
padding_value does not equal dynamic_extent,
then other.stride(rank_ - 2) equals
LEAST-MULTIPLE-AT-LEAST(padding_value,
extents_type::index-cast(other.extents().extent(rank_ - 1)))
If
rank_ is greater than 0,
then other.stride(
rank_ - 1) equals 1
.If rank_ is greater than 2,
then for all r in the range [0, rank_ - 2),
other.stride(r) equals
(other.extents().rev-prod-of-extents(r) / other.extents().extent(rank_ - 1)) *
other.stride(rank_ - 2)
other.required_span_size() is representable as
a value of type
index_type.
Effects:
- Direct-non-list-initializes extents_ with other.extents(); and
- if rank_ is greater than one,
direct-non-list-initializes stride-rm2
with other.stride(rank_ - 2).
template<class LayoutRightPaddedMapping>
constexpr explicit(see below)
mapping(const LayoutRightPaddedMapping& other);
Constraints:
is-layout-right-padded-mapping-of<LayoutRightPaddedMapping>
is
true. is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-
type>
is
true.
Mandates: If
rank_ is greater than 1, then
padding_value == dynamic_extent ||
LayoutRightPaddedMapping::padding_value == dynamic_extent ||
padding_value == LayoutRightPaddedMapping::padding_value
is
true. Preconditions:
- If rank_ is greater than 1 and
padding_value does not equal dynamic_extent,
then other.stride(rank_ - 2) equals
LEAST-MULTIPLE-AT-LEAST(padding_value,
extents_type::index-cast(other.extent(rank_ - 1)))
- other.required_span_size() is representable as
a value of type index_type.
Effects:
- Direct-non-list-initializes extents_ with other.extents(); and
- if rank_ is greater than one,
direct-non-list-initializes stride-rm2
with other.stride(rank_ - 2).
Remarks: The expression inside explicit is equivalent to:
rank_ > 1 &&
(padding_value != dynamic_extent ||
LayoutRightPaddedMapping::padding_value == dynamic_extent)
template<class LayoutLeftPaddedMapping>
constexpr explicit(see below)
mapping(const LayoutLeftPaddedMapping& other) noexcept;
Constraints:
is-layout-left-padded-mapping-of<LayoutLeftPaddedMapping>
is
true or
is-mapping-of<layout_left, LayoutLeftPaddedMapping>
is
true. rank_ equals zero or one
. is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>is
true.
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]
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:
sizeof...(Indices) == rank_ is
true. (is_convertible_v<Indices, index_type> && ...) is
true. (is_nothrow_constructible_v<index_type, Indices> && ...) is
true.
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:
- If rank_ equals zero or one, then true;
- otherwise,
if neither static-padding-stride nor last-static-extent
equal dynamic_extent,
then static-padding-stride == last-static-extent;
- otherwise, false.
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:
- If r equals rank_ - 1: 1;
- otherwise, if r equals rank_ - 2: stride-rm2;
- otherwise,
the product of stride-rm2 and
all values extents_.extent(k)
with k in the range of [r + 1, rank_ - 1).
template<class LayoutRightPaddedMapping>
friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept;
Constraints:
is-layout-right-padded-mapping-of<LayoutRightPaddedMapping>
is
true. LayoutRightPaddedMapping::extents_type::rank() == rank_
is
true.
Returns:
true if
x.extents() == y.extents() is
true and
rank_ < 2 || x.stride(rank_ - 2) == y.stride(rank_ - 2) is
true.