[mdspan.layout.stride] (original) (raw)
23 Containers library [containers]
23.7 Views [views]
23.7.3 Multidimensional access [views.multidim]
23.7.3.4 Layout mapping [mdspan.layout]
23.7.3.4.7 Class template layout_stride::mapping [mdspan.layout.stride]
23.7.3.4.7.1 Overview [mdspan.layout.stride.overview]
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 = typename extents_type::index_type;using size_type = typename extents_type::size_type;using rank_type = typename 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.
23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]
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) andextents_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 zthat 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 functionsM::is_always_strided(),M::is_always_exhaustive(), andM::is_always_unique() exist, are constant expressions, and have a return type of bool.
— _end note_]
23.7.3.4.7.3 Constructors [mdspan.layout.stride.cons]
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] withlayout_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_typeis greater than 0for 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[] >= s[] * e.extent(p) is truefor all i in the range [1, rank__), where is the 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:
- layout-mapping-alike<StridedLayoutMapping> is satisfied.
- is_constructible_v<extents_type, typename StridedLayoutMapping::extents_type> is
true. - 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 truefor 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>))
23.7.3.4.7.4 Observers [mdspan.layout.stride.obs]
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 thatis_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() equals 1, andstride() equals stride() * extents().extent()for i in the range [1, _rank__), where is the element of P.
template<class OtherMapping> friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept;
Constraints:
- layout-mapping-alike<OtherMapping> is satisfied.
- 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 truefor r in the range [0, x.extents().rank()).
Otherwise, false.