Files
cppdraft_translate/cppdraft/mdspan/mdspan.md
2025-10-25 03:02:53 +03:00

23 KiB
Raw Blame History

[mdspan.mdspan]

23 Containers library [containers]

23.7 Views [views]

23.7.3 Multidimensional access [views.multidim]

23.7.3.6 Class template mdspan [mdspan.mdspan]

23.7.3.6.1 Overview [mdspan.mdspan.overview]

1

#

mdspan is a view of a multidimensional array of elements.

namespace std {template<class ElementType, class Extents, class LayoutPolicy = layout_right, class AccessorPolicy = default_accessor>class mdspan {public:using extents_type = Extents; using layout_type = LayoutPolicy; using accessor_type = AccessorPolicy; using mapping_type = typename layout_type::template mapping<extents_type>; using element_type = ElementType; using value_type = remove_cv_t<element_type>; 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 data_handle_type = typename accessor_type::data_handle_type; using reference = typename accessor_type::reference; static constexpr rank_type rank() noexcept { return extents_type::rank(); }static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }static constexpr size_t static_extent(rank_type r) noexcept{ return extents_type::static_extent(r); }constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); }// [mdspan.mdspan.cons], constructorsconstexpr mdspan(); constexpr mdspan(const mdspan& rhs) = default; constexpr mdspan(mdspan&& rhs) = default; template<class... OtherIndexTypes>constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts); template<class OtherIndexType, size_t N>constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span<OtherIndexType, N> exts); template<class OtherIndexType, size_t N>constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array<OtherIndexType, N>& exts); constexpr mdspan(data_handle_type p, const extents_type& ext); constexpr mdspan(data_handle_type p, const mapping_type& m); constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); template<class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessorPolicy>constexpr explicit(see below) mdspan(const mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessorPolicy>& other); constexpr mdspan& operator=(const mdspan& rhs) = default; constexpr mdspan& operator=(mdspan&& rhs) = default; // [mdspan.mdspan.members], memberstemplate<class... OtherIndexTypes>constexpr reference operator[](OtherIndexTypes... indices) const; templateconstexpr reference operator[](span<OtherIndexType, rank()> indices) const; templateconstexpr reference operator[](const array<OtherIndexType, rank()>& indices) const; template<class... OtherIndexTypes>constexpr reference at(OtherIndexTypes... indices) const; // freestanding-deletedtemplateconstexpr reference at(span<OtherIndexType, rank()> indices) const; // freestanding-deletedtemplateconstexpr reference at(const array<OtherIndexType, rank()>& indices) const; // freestanding-deletedconstexpr size_type size() const noexcept; constexpr bool empty() const noexcept; friend constexpr void swap(mdspan& x, mdspan& y) noexcept; constexpr const extents_type& extents() const noexcept { return map_.extents(); }constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }constexpr const mapping_type& mapping() const noexcept { return map_; }constexpr const accessor_type& accessor() const noexcept { return acc_; }static constexpr bool is_always_unique(){ return mapping_type::is_always_unique(); }static constexpr bool is_always_exhaustive(){ return mapping_type::is_always_exhaustive(); }static constexpr bool is_always_strided(){ return mapping_type::is_always_strided(); }constexpr bool is_unique() const{ return map_.is_unique(); }constexpr bool is_exhaustive() const{ return map_.is_exhaustive(); }constexpr bool is_strided() const{ return map_.is_strided(); }constexpr index_type stride(rank_type r) const{ return map_.stride(r); }private: accessor_type acc_; // exposition only mapping_type map_; // exposition only data_handle_type ptr_; // exposition only}; templaterequires (is_array_v && rank_v == 1) mdspan(CArray&)-> mdspan<remove_all_extents_t, extents<size_t, extent_v<CArray, 0>>>; templaterequires (is_pointer_v<remove_reference_t>) mdspan(Pointer&&)-> mdspan<remove_pointer_t<remove_reference_t>, extents<size_t>>; template<class ElementType, class... Integrals>requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)explicit mdspan(ElementType*, Integrals...)-> mdspan<ElementType, extents<size_t, maybe-static-ext...>>; template<class ElementType, class OtherIndexType, size_t N> mdspan(ElementType*, span<OtherIndexType, N>)-> mdspan<ElementType, dextents<size_t, N>>; template<class ElementType, class OtherIndexType, size_t N> mdspan(ElementType*, const array<OtherIndexType, N>&)-> mdspan<ElementType, dextents<size_t, N>>; template<class ElementType, class IndexType, size_t... ExtentsPack> mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)-> mdspan<ElementType, extents<IndexType, ExtentsPack...>>; template<class ElementType, class MappingType> mdspan(ElementType*, const MappingType&)-> mdspan<ElementType, typename MappingType::extents_type, typename MappingType::layout_type>; template<class MappingType, class AccessorType> mdspan(const typename AccessorType::data_handle_type&, const MappingType&, const AccessorType&)-> mdspan<typename AccessorType::element_type, typename MappingType::extents_type, typename MappingType::layout_type, AccessorType>;}

2

#

Mandates:

ElementType is a complete object type that is neither an abstract class type nor an array type,

Extents is a specialization of extents, and

is_same_v<ElementType, typename AccessorPolicy::element_type> is true.

3

#

LayoutPolicy shall meet the layout mapping policy requirements ([mdspan.layout.policy.reqmts]), andAccessorPolicy shall meet the accessor policy requirements ([mdspan.accessor.reqmts]).

4

#

Each specialization MDS of mdspan models copyable and

is_nothrow_move_constructible_v is true,

is_nothrow_move_assignable_v is true, and

is_nothrow_swappable_v is true.

5

#

A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_type are trivially copyable types.

23.7.3.6.2 Constructors [mdspan.mdspan.cons]

🔗

constexpr mdspan();

1

#

Constraints:

  • (1.1)

    rank_dynamic() > 0 is true.

  • (1.2)

    is_default_constructible_v<data_handle_type> is true.

  • (1.3)

    is_default_constructible_v<mapping_type> is true.

  • (1.4)

    is_default_constructible_v<accessor_type> is true.

2

#

Preconditions: [0, map_.required_span_size()) is an accessible range of ptr_ and acc_ for the values of map_ and acc_ after the invocation of this constructor.

3

#

Effects: Value-initializes ptr_, map_, and acc_.

🔗

template<class... OtherIndexTypes> constexpr explicit mdspan(data_handle_type p, OtherIndexTypes... exts);

4

#

Let N be sizeof...(OtherIndexTypes).

5

#

Constraints:

(is_convertible_v<OtherIndexTypes, index_type> && ...) is true,

(is_nothrow_constructible<index_type, OtherIndexTypes> && ...) is true,

N == rank() || N == rank_dynamic() is true,

is_constructible_v<mapping_type, extents_type> is true, and

is_default_constructible_v<accessor_type> is true.

6

#

Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ for the values of map_ and acc_ after the invocation of this constructor.

7

#

Effects:

Direct-non-list-initializes ptr_ with std::move(p),

direct-non-list-initializes map_ withextents_type(static_cast<index_type>(std::move(exts))...), and

value-initializes acc_.

🔗

template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span<OtherIndexType, N> exts); template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);

8

#

Constraints:

is_convertible_v<const OtherIndexType&, index_type> is true,

is_nothrow_constructible_v<index_type, const OtherIndexType&> is true,

N == rank() || N == rank_dynamic() is true,

is_constructible_v<mapping_type, extents_type> is true, and

is_default_constructible_v<accessor_type> is true.

9

#

Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ for the values of map_ and acc_ after the invocation of this constructor.

10

#

Effects:

Direct-non-list-initializes ptr_ with std::move(p),

direct-non-list-initializes map_ with extents_type(exts), and

value-initializes acc_.

🔗

constexpr mdspan(data_handle_type p, const extents_type& ext);

11

#

Constraints:

is_constructible_v<mapping_type, const extents_type&> is true, and

is_default_constructible_v<accessor_type> is true.

12

#

Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ for the values of map_ and acc_ after the invocation of this constructor.

13

#

Effects:

Direct-non-list-initializes ptr_ with std::move(p),

direct-non-list-initializes map_ with ext, and

value-initializes acc_.

🔗

constexpr mdspan(data_handle_type p, const mapping_type& m);

14

#

Constraints: is_default_constructible_v<accessor_type> is true.

15

#

Preconditions: [0, m.required_span_size()) is an accessible range of p and acc_ for the value of acc_ after the invocation of this constructor.

16

#

Effects:

Direct-non-list-initializes ptr_ with std::move(p),

direct-non-list-initializes map_ with m, and

value-initializes acc_.

🔗

constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);

17

#

Preconditions: [0, m.required_span_size()) is an accessible range of p and a.

18

#

Effects:

Direct-non-list-initializes ptr_ with std::move(p),

direct-non-list-initializes map_ with m, and

direct-non-list-initializes acc_ with a.

🔗

template<class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessor> constexpr explicit(see below) mdspan(const mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessor>& other);

19

#

Constraints:

is_constructible_v<mapping_type, const OtherLayoutPolicy::template mapping&> is true, and

is_constructible_v<accessor_type, const OtherAccessor&> is true.

20

#

Mandates:

is_constructible_v<data_handle_type, const OtherAccessor::data_handle_type&> is
true, and

is_constructible_v<extents_type, OtherExtents> is true.

21

#

Preconditions: [0, map_.required_span_size()) is an accessible range of ptr_ and acc_ for values of ptr_, map_, and acc_ after the invocation of this constructor.

22

#

Hardened preconditions: For each rank index r of extents_type,static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r) is true.

23

#

Effects:

Direct-non-list-initializes ptr_ with other.ptr_,

direct-non-list-initializes map_ with other.map_, and

direct-non-list-initializes acc_ with other.acc_.

24

#

Remarks: The expression inside explicit is equivalent to:!is_convertible_v<const OtherLayoutPolicy::template mapping&, mapping_type>|| !is_convertible_v<const OtherAccessor&, accessor_type>

23.7.3.6.3 Members [mdspan.mdspan.members]

🔗

template<class... OtherIndexTypes> constexpr reference operator[](OtherIndexTypes... indices) const;

1

#

Constraints:

(is_convertible_v<OtherIndexTypes, index_type> && ...) is true,

(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) is true, and

sizeof...(OtherIndexTypes) == rank() is true.

2

#

Let I be extents_type::index-cast(std::move(indices)).

3

#

Hardened preconditions: I is a multidimensional index in extents().

[Note 1:

This implies thatmap_(I) < map_.required_span_size() is true.

— end note]

4

#

Effects: Equivalent to:return acc_.access(ptr_, map_(static_cast<index_type>(std::move(indices))...));

🔗

template<class OtherIndexType> constexpr reference operator[](span<OtherIndexType, rank()> indices) const; template<class OtherIndexType> constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;

5

#

Constraints:

is_convertible_v<const OtherIndexType&, index_type> is true, and

is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.

6

#

Effects: Let P be a parameter pack such thatis_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true.

Equivalent to:return operator;

🔗

template<class... OtherIndexTypes> constexpr reference at(OtherIndexTypes... indices) const;

7

#

Constraints:

(is_convertible_v<OtherIndexTypes, index_type> && ...) is true,

(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) is true, and

sizeof...(OtherIndexTypes) == rank() is true.

8

#

Let I be extents_type::index-cast(std::move(indices)).

9

#

Returns: (*this)[I...].

10

#

Throws: out_of_range if I is not a multidimensional index in extents().

🔗

template<class OtherIndexType> constexpr reference at(span<OtherIndexType, rank()> indices) const; template<class OtherIndexType> constexpr reference at(const array<OtherIndexType, rank()>& indices) const;

11

#

Constraints:

is_convertible_v<const OtherIndexType&, index_type> is true, and

is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.

12

#

Effects: Let P be a parameter pack such thatis_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true.

Equivalent to:return at(extents_type::index-cast(as_const(indices[P]))...);

🔗

constexpr size_type size() const noexcept;

13

#

Preconditions: The size of the multidimensional index space extents() is representable as a value of type size_type ([basic.fundamental]).

14

#

Returns: extents().fwd-prod-of-extents(rank()).

🔗

constexpr bool empty() const noexcept;

15

#

Returns: true if the size of the multidimensional index space extents() is 0, otherwise false.

🔗

friend constexpr void swap(mdspan& x, mdspan& y) noexcept;

16

#

Effects: Equivalent to:swap(x.ptr_, y.ptr_); swap(x.map_, y.map_); swap(x.acc_, y.acc_);