xref: /freebsd/contrib/llvm-project/libcxx/include/mdspan (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric// -*- C++ -*-
206c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
306c3fb27SDimitry Andric//
406c3fb27SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
506c3fb27SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
606c3fb27SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
706c3fb27SDimitry Andric//
806c3fb27SDimitry Andric//===---------------------------------------------------------------------===//
906c3fb27SDimitry Andric
1006c3fb27SDimitry Andric/*
1106c3fb27SDimitry Andric
1206c3fb27SDimitry Andric// Overall mdspan synopsis
1306c3fb27SDimitry Andric
1406c3fb27SDimitry Andricnamespace std {
1506c3fb27SDimitry Andric  // [mdspan.extents], class template extents
1606c3fb27SDimitry Andric  template<class IndexType, size_t... Extents>
1706c3fb27SDimitry Andric    class extents;
1806c3fb27SDimitry Andric
1906c3fb27SDimitry Andric  // [mdspan.extents.dextents], alias template dextents
2006c3fb27SDimitry Andric  template<class IndexType, size_t Rank>
2106c3fb27SDimitry Andric    using dextents = see below;
2206c3fb27SDimitry Andric
23*0fca6ea1SDimitry Andric  // [mdspan.extents.dims], alias template dims
24*0fca6ea1SDimitry Andric  template<size_t Rank, class IndexType = size_t>
25*0fca6ea1SDimitry Andric    using dims = see below; // since C++26
26*0fca6ea1SDimitry Andric
2706c3fb27SDimitry Andric  // [mdspan.layout], layout mapping
2806c3fb27SDimitry Andric  struct layout_left;
2906c3fb27SDimitry Andric  struct layout_right;
305f757f3fSDimitry Andric  struct layout_stride;
3106c3fb27SDimitry Andric
3206c3fb27SDimitry Andric  // [mdspan.accessor.default], class template default_accessor
3306c3fb27SDimitry Andric  template<class ElementType>
3406c3fb27SDimitry Andric    class default_accessor;
3506c3fb27SDimitry Andric
3606c3fb27SDimitry Andric  // [mdspan.mdspan], class template mdspan
3706c3fb27SDimitry Andric  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
3806c3fb27SDimitry Andric           class AccessorPolicy = default_accessor<ElementType>>
3906c3fb27SDimitry Andric    class mdspan; // not implemented yet
4006c3fb27SDimitry Andric}
4106c3fb27SDimitry Andric
4206c3fb27SDimitry Andric// extents synopsis
4306c3fb27SDimitry Andric
4406c3fb27SDimitry Andricnamespace std {
4506c3fb27SDimitry Andric  template<class _IndexType, size_t... _Extents>
4606c3fb27SDimitry Andric  class extents {
4706c3fb27SDimitry Andric  public:
4806c3fb27SDimitry Andric    using index_type = _IndexType;
4906c3fb27SDimitry Andric    using size_type = make_unsigned_t<index_type>;
5006c3fb27SDimitry Andric    using rank_type = size_t;
5106c3fb27SDimitry Andric
5206c3fb27SDimitry Andric    // [mdspan.extents.obs], observers of the multidimensional index space
5306c3fb27SDimitry Andric    static constexpr rank_type rank() noexcept { return sizeof...(_Extents); }
5406c3fb27SDimitry Andric    static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); }
5506c3fb27SDimitry Andric    static constexpr size_t static_extent(rank_type) noexcept;
5606c3fb27SDimitry Andric    constexpr index_type extent(rank_type) const noexcept;
5706c3fb27SDimitry Andric
5806c3fb27SDimitry Andric    // [mdspan.extents.cons], constructors
5906c3fb27SDimitry Andric    constexpr extents() noexcept = default;
6006c3fb27SDimitry Andric
6106c3fb27SDimitry Andric    template<class _OtherIndexType, size_t... _OtherExtents>
6206c3fb27SDimitry Andric      constexpr explicit(see below)
6306c3fb27SDimitry Andric        extents(const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
6406c3fb27SDimitry Andric    template<class... _OtherIndexTypes>
6506c3fb27SDimitry Andric      constexpr explicit extents(_OtherIndexTypes...) noexcept;
6606c3fb27SDimitry Andric    template<class _OtherIndexType, size_t N>
6706c3fb27SDimitry Andric      constexpr explicit(N != rank_dynamic())
6806c3fb27SDimitry Andric        extents(span<_OtherIndexType, N>) noexcept;
6906c3fb27SDimitry Andric    template<class _OtherIndexType, size_t N>
7006c3fb27SDimitry Andric      constexpr explicit(N != rank_dynamic())
7106c3fb27SDimitry Andric        extents(const array<_OtherIndexType, N>&) noexcept;
7206c3fb27SDimitry Andric
7306c3fb27SDimitry Andric    // [mdspan.extents.cmp], comparison operators
7406c3fb27SDimitry Andric    template<class _OtherIndexType, size_t... _OtherExtents>
7506c3fb27SDimitry Andric      friend constexpr bool operator==(const extents&,
7606c3fb27SDimitry Andric                                       const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
7706c3fb27SDimitry Andric
7806c3fb27SDimitry Andric  private:
7906c3fb27SDimitry Andric    // libcxx note: we do not use an array here, but we need to preserve the as-if behavior
8006c3fb27SDimitry Andric    // for example the default constructor must zero initialize dynamic extents
8106c3fb27SDimitry Andric    array<index_type, rank_dynamic()> dynamic-extents{};                // exposition only
8206c3fb27SDimitry Andric  };
8306c3fb27SDimitry Andric
8406c3fb27SDimitry Andric  template<class... Integrals>
8506c3fb27SDimitry Andric    explicit extents(Integrals...)
8606c3fb27SDimitry Andric      -> see below;
8706c3fb27SDimitry Andric}
8806c3fb27SDimitry Andric
8906c3fb27SDimitry Andric// layout_left synopsis
9006c3fb27SDimitry Andric
9106c3fb27SDimitry Andricnamespace std {
9206c3fb27SDimitry Andric  template<class Extents>
9306c3fb27SDimitry Andric  class layout_left::mapping {
9406c3fb27SDimitry Andric  public:
9506c3fb27SDimitry Andric    using extents_type = Extents;
9606c3fb27SDimitry Andric    using index_type = typename extents_type::index_type;
9706c3fb27SDimitry Andric    using size_type = typename extents_type::size_type;
9806c3fb27SDimitry Andric    using rank_type = typename extents_type::rank_type;
9906c3fb27SDimitry Andric    using layout_type = layout_left;
10006c3fb27SDimitry Andric
10106c3fb27SDimitry Andric    // [mdspan.layout.right.cons], constructors
10206c3fb27SDimitry Andric    constexpr mapping() noexcept = default;
10306c3fb27SDimitry Andric    constexpr mapping(const mapping&) noexcept = default;
10406c3fb27SDimitry Andric    constexpr mapping(const extents_type&) noexcept;
10506c3fb27SDimitry Andric    template<class OtherExtents>
10606c3fb27SDimitry Andric      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
10706c3fb27SDimitry Andric        mapping(const mapping<OtherExtents>&) noexcept;
10806c3fb27SDimitry Andric    template<class OtherExtents>
10906c3fb27SDimitry Andric      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
11006c3fb27SDimitry Andric        mapping(const layout_right::mapping<OtherExtents>&) noexcept;
11106c3fb27SDimitry Andric    template<class OtherExtents>
11206c3fb27SDimitry Andric      constexpr explicit(extents_type::rank() > 0)
11306c3fb27SDimitry Andric        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
11406c3fb27SDimitry Andric
11506c3fb27SDimitry Andric    constexpr mapping& operator=(const mapping&) noexcept = default;
11606c3fb27SDimitry Andric
11706c3fb27SDimitry Andric    // [mdspan.layout.right.obs], observers
11806c3fb27SDimitry Andric    constexpr const extents_type& extents() const noexcept { return extents_; }
11906c3fb27SDimitry Andric
12006c3fb27SDimitry Andric    constexpr index_type required_span_size() const noexcept;
12106c3fb27SDimitry Andric
12206c3fb27SDimitry Andric    template<class... Indices>
12306c3fb27SDimitry Andric      constexpr index_type operator()(Indices...) const noexcept;
12406c3fb27SDimitry Andric
12506c3fb27SDimitry Andric    static constexpr bool is_always_unique() noexcept { return true; }
12606c3fb27SDimitry Andric    static constexpr bool is_always_exhaustive() noexcept { return true; }
12706c3fb27SDimitry Andric    static constexpr bool is_always_strided() noexcept { return true; }
12806c3fb27SDimitry Andric
12906c3fb27SDimitry Andric    static constexpr bool is_unique() noexcept { return true; }
13006c3fb27SDimitry Andric    static constexpr bool is_exhaustive() noexcept { return true; }
13106c3fb27SDimitry Andric    static constexpr bool is_strided() noexcept { return true; }
13206c3fb27SDimitry Andric
13306c3fb27SDimitry Andric    constexpr index_type stride(rank_type) const noexcept;
13406c3fb27SDimitry Andric
13506c3fb27SDimitry Andric    template<class OtherExtents>
13606c3fb27SDimitry Andric      friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
13706c3fb27SDimitry Andric
13806c3fb27SDimitry Andric  private:
13906c3fb27SDimitry Andric    extents_type extents_{};    // exposition only
14006c3fb27SDimitry Andric  };
14106c3fb27SDimitry Andric}
14206c3fb27SDimitry Andric
14306c3fb27SDimitry Andric// layout_right synopsis
14406c3fb27SDimitry Andric
14506c3fb27SDimitry Andricnamespace std {
14606c3fb27SDimitry Andric  template<class Extents>
14706c3fb27SDimitry Andric  class layout_right::mapping {
14806c3fb27SDimitry Andric  public:
14906c3fb27SDimitry Andric    using extents_type = Extents;
15006c3fb27SDimitry Andric    using index_type = typename extents_type::index_type;
15106c3fb27SDimitry Andric    using size_type = typename extents_type::size_type;
15206c3fb27SDimitry Andric    using rank_type = typename extents_type::rank_type;
15306c3fb27SDimitry Andric    using layout_type = layout_right;
15406c3fb27SDimitry Andric
15506c3fb27SDimitry Andric    // [mdspan.layout.right.cons], constructors
15606c3fb27SDimitry Andric    constexpr mapping() noexcept = default;
15706c3fb27SDimitry Andric    constexpr mapping(const mapping&) noexcept = default;
15806c3fb27SDimitry Andric    constexpr mapping(const extents_type&) noexcept;
15906c3fb27SDimitry Andric    template<class OtherExtents>
16006c3fb27SDimitry Andric      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
16106c3fb27SDimitry Andric        mapping(const mapping<OtherExtents>&) noexcept;
16206c3fb27SDimitry Andric    template<class OtherExtents>
16306c3fb27SDimitry Andric      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
16406c3fb27SDimitry Andric        mapping(const layout_left::mapping<OtherExtents>&) noexcept;
16506c3fb27SDimitry Andric    template<class OtherExtents>
16606c3fb27SDimitry Andric      constexpr explicit(extents_type::rank() > 0)
16706c3fb27SDimitry Andric        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
16806c3fb27SDimitry Andric
16906c3fb27SDimitry Andric    constexpr mapping& operator=(const mapping&) noexcept = default;
17006c3fb27SDimitry Andric
17106c3fb27SDimitry Andric    // [mdspan.layout.right.obs], observers
17206c3fb27SDimitry Andric    constexpr const extents_type& extents() const noexcept { return extents_; }
17306c3fb27SDimitry Andric
17406c3fb27SDimitry Andric    constexpr index_type required_span_size() const noexcept;
17506c3fb27SDimitry Andric
17606c3fb27SDimitry Andric    template<class... Indices>
17706c3fb27SDimitry Andric      constexpr index_type operator()(Indices...) const noexcept;
17806c3fb27SDimitry Andric
17906c3fb27SDimitry Andric    static constexpr bool is_always_unique() noexcept { return true; }
18006c3fb27SDimitry Andric    static constexpr bool is_always_exhaustive() noexcept { return true; }
18106c3fb27SDimitry Andric    static constexpr bool is_always_strided() noexcept { return true; }
18206c3fb27SDimitry Andric
18306c3fb27SDimitry Andric    static constexpr bool is_unique() noexcept { return true; }
18406c3fb27SDimitry Andric    static constexpr bool is_exhaustive() noexcept { return true; }
18506c3fb27SDimitry Andric    static constexpr bool is_strided() noexcept { return true; }
18606c3fb27SDimitry Andric
18706c3fb27SDimitry Andric    constexpr index_type stride(rank_type) const noexcept;
18806c3fb27SDimitry Andric
18906c3fb27SDimitry Andric    template<class OtherExtents>
19006c3fb27SDimitry Andric      friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
19106c3fb27SDimitry Andric
19206c3fb27SDimitry Andric  private:
19306c3fb27SDimitry Andric    extents_type extents_{};    // exposition only
19406c3fb27SDimitry Andric  };
19506c3fb27SDimitry Andric}
19606c3fb27SDimitry Andric
1975f757f3fSDimitry Andric// layout_stride synopsis
1985f757f3fSDimitry Andric
1995f757f3fSDimitry Andricnamespace std {
2005f757f3fSDimitry Andric  template<class Extents>
2015f757f3fSDimitry Andric  class layout_stride::mapping {
2025f757f3fSDimitry Andric  public:
2035f757f3fSDimitry Andric    using extents_type = Extents;
2045f757f3fSDimitry Andric    using index_type = typename extents_type::index_type;
2055f757f3fSDimitry Andric    using size_type = typename extents_type::size_type;
2065f757f3fSDimitry Andric    using rank_type = typename extents_type::rank_type;
2075f757f3fSDimitry Andric    using layout_type = layout_stride;
2085f757f3fSDimitry Andric
2095f757f3fSDimitry Andric  private:
2105f757f3fSDimitry Andric    static constexpr rank_type rank_ = extents_type::rank();    // exposition only
2115f757f3fSDimitry Andric
2125f757f3fSDimitry Andric  public:
2135f757f3fSDimitry Andric    // [mdspan.layout.stride.cons], constructors
2145f757f3fSDimitry Andric    constexpr mapping() noexcept;
2155f757f3fSDimitry Andric    constexpr mapping(const mapping&) noexcept = default;
2165f757f3fSDimitry Andric    template<class OtherIndexType>
2175f757f3fSDimitry Andric      constexpr mapping(const extents_type&, span<OtherIndexType, rank_>) noexcept;
2185f757f3fSDimitry Andric    template<class OtherIndexType>
2195f757f3fSDimitry Andric      constexpr mapping(const extents_type&, const array<OtherIndexType, rank_>&) noexcept;
2205f757f3fSDimitry Andric
2215f757f3fSDimitry Andric    template<class StridedLayoutMapping>
2225f757f3fSDimitry Andric      constexpr explicit(see below) mapping(const StridedLayoutMapping&) noexcept;
2235f757f3fSDimitry Andric
2245f757f3fSDimitry Andric    constexpr mapping& operator=(const mapping&) noexcept = default;
2255f757f3fSDimitry Andric
2265f757f3fSDimitry Andric    // [mdspan.layout.stride.obs], observers
2275f757f3fSDimitry Andric    constexpr const extents_type& extents() const noexcept { return extents_; }
2285f757f3fSDimitry Andric    constexpr array<index_type, rank_> strides() const noexcept { return strides_; }
2295f757f3fSDimitry Andric
2305f757f3fSDimitry Andric    constexpr index_type required_span_size() const noexcept;
2315f757f3fSDimitry Andric
2325f757f3fSDimitry Andric    template<class... Indices>
2335f757f3fSDimitry Andric      constexpr index_type operator()(Indices...) const noexcept;
2345f757f3fSDimitry Andric
2355f757f3fSDimitry Andric    static constexpr bool is_always_unique() noexcept { return true; }
2365f757f3fSDimitry Andric    static constexpr bool is_always_exhaustive() noexcept { return false; }
2375f757f3fSDimitry Andric    static constexpr bool is_always_strided() noexcept { return true; }
2385f757f3fSDimitry Andric
2395f757f3fSDimitry Andric    static constexpr bool is_unique() noexcept { return true; }
2405f757f3fSDimitry Andric    constexpr bool is_exhaustive() const noexcept;
2415f757f3fSDimitry Andric    static constexpr bool is_strided() noexcept { return true; }
2425f757f3fSDimitry Andric
2435f757f3fSDimitry Andric    constexpr index_type stride(rank_type i) const noexcept { return strides_[i]; }
2445f757f3fSDimitry Andric
2455f757f3fSDimitry Andric    template<class OtherMapping>
2465f757f3fSDimitry Andric      friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
2475f757f3fSDimitry Andric
2485f757f3fSDimitry Andric  private:
2495f757f3fSDimitry Andric    extents_type extents_{};                    // exposition only
2505f757f3fSDimitry Andric    array<index_type, rank_> strides_{};        // exposition only
2515f757f3fSDimitry Andric  };
2525f757f3fSDimitry Andric}
2535f757f3fSDimitry Andric
25406c3fb27SDimitry Andric// default_accessor synopsis
25506c3fb27SDimitry Andric
25606c3fb27SDimitry Andricnamespace std {
25706c3fb27SDimitry Andric  template<class ElementType>
25806c3fb27SDimitry Andric  struct default_accessor {
25906c3fb27SDimitry Andric    using offset_policy = default_accessor;
26006c3fb27SDimitry Andric    using element_type = ElementType;
26106c3fb27SDimitry Andric    using reference = ElementType&;
26206c3fb27SDimitry Andric    using data_handle_type = ElementType*;
26306c3fb27SDimitry Andric
26406c3fb27SDimitry Andric    constexpr default_accessor() noexcept = default;
26506c3fb27SDimitry Andric    template<class OtherElementType>
26606c3fb27SDimitry Andric      constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
26706c3fb27SDimitry Andric    constexpr reference access(data_handle_type p, size_t i) const noexcept;
26806c3fb27SDimitry Andric    constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
26906c3fb27SDimitry Andric  };
27006c3fb27SDimitry Andric}
27106c3fb27SDimitry Andric
2728a4dda33SDimitry Andric// mdspan synopsis
2738a4dda33SDimitry Andric
2748a4dda33SDimitry Andricnamespace std {
2758a4dda33SDimitry Andric  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
2768a4dda33SDimitry Andric           class AccessorPolicy = default_accessor<ElementType>>
2778a4dda33SDimitry Andric  class mdspan {
2788a4dda33SDimitry Andric  public:
2798a4dda33SDimitry Andric    using extents_type = Extents;
2808a4dda33SDimitry Andric    using layout_type = LayoutPolicy;
2818a4dda33SDimitry Andric    using accessor_type = AccessorPolicy;
2828a4dda33SDimitry Andric    using mapping_type = typename layout_type::template mapping<extents_type>;
2838a4dda33SDimitry Andric    using element_type = ElementType;
2848a4dda33SDimitry Andric    using value_type = remove_cv_t<element_type>;
2858a4dda33SDimitry Andric    using index_type = typename extents_type::index_type;
2868a4dda33SDimitry Andric    using size_type = typename extents_type::size_type;
2878a4dda33SDimitry Andric    using rank_type = typename extents_type::rank_type;
2888a4dda33SDimitry Andric    using data_handle_type = typename accessor_type::data_handle_type;
2898a4dda33SDimitry Andric    using reference = typename accessor_type::reference;
2908a4dda33SDimitry Andric
2918a4dda33SDimitry Andric    static constexpr rank_type rank() noexcept { return extents_type::rank(); }
2928a4dda33SDimitry Andric    static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
2938a4dda33SDimitry Andric    static constexpr size_t static_extent(rank_type r) noexcept
2948a4dda33SDimitry Andric      { return extents_type::static_extent(r); }
2958a4dda33SDimitry Andric    constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); }
2968a4dda33SDimitry Andric
2978a4dda33SDimitry Andric    // [mdspan.mdspan.cons], constructors
2988a4dda33SDimitry Andric    constexpr mdspan();
2998a4dda33SDimitry Andric    constexpr mdspan(const mdspan& rhs) = default;
3008a4dda33SDimitry Andric    constexpr mdspan(mdspan&& rhs) = default;
3018a4dda33SDimitry Andric
3028a4dda33SDimitry Andric    template<class... OtherIndexTypes>
3038a4dda33SDimitry Andric      constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts);
3048a4dda33SDimitry Andric    template<class OtherIndexType, size_t N>
3058a4dda33SDimitry Andric      constexpr explicit(N != rank_dynamic())
3068a4dda33SDimitry Andric        mdspan(data_handle_type p, span<OtherIndexType, N> exts);
3078a4dda33SDimitry Andric    template<class OtherIndexType, size_t N>
3088a4dda33SDimitry Andric      constexpr explicit(N != rank_dynamic())
3098a4dda33SDimitry Andric        mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
3108a4dda33SDimitry Andric    constexpr mdspan(data_handle_type p, const extents_type& ext);
3118a4dda33SDimitry Andric    constexpr mdspan(data_handle_type p, const mapping_type& m);
3128a4dda33SDimitry Andric    constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
3138a4dda33SDimitry Andric
3148a4dda33SDimitry Andric    template<class OtherElementType, class OtherExtents,
3158a4dda33SDimitry Andric             class OtherLayoutPolicy, class OtherAccessorPolicy>
3168a4dda33SDimitry Andric      constexpr explicit(see below)
3178a4dda33SDimitry Andric        mdspan(const mdspan<OtherElementType, OtherExtents,
3188a4dda33SDimitry Andric                            OtherLayoutPolicy, OtherAccessorPolicy>& other);
3198a4dda33SDimitry Andric
3208a4dda33SDimitry Andric    constexpr mdspan& operator=(const mdspan& rhs) = default;
3218a4dda33SDimitry Andric    constexpr mdspan& operator=(mdspan&& rhs) = default;
3228a4dda33SDimitry Andric
3238a4dda33SDimitry Andric    // [mdspan.mdspan.members], members
3248a4dda33SDimitry Andric    template<class... OtherIndexTypes>
3258a4dda33SDimitry Andric      constexpr reference operator[](OtherIndexTypes... indices) const;
3268a4dda33SDimitry Andric    template<class OtherIndexType>
3278a4dda33SDimitry Andric      constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
3288a4dda33SDimitry Andric    template<class OtherIndexType>
3298a4dda33SDimitry Andric      constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
3308a4dda33SDimitry Andric
3318a4dda33SDimitry Andric    constexpr size_type size() const noexcept;
3328a4dda33SDimitry Andric    [[nodiscard]] constexpr bool empty() const noexcept;
3338a4dda33SDimitry Andric
3348a4dda33SDimitry Andric    friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
3358a4dda33SDimitry Andric
3368a4dda33SDimitry Andric    constexpr const extents_type& extents() const noexcept { return map_.extents(); }
3378a4dda33SDimitry Andric    constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
3388a4dda33SDimitry Andric    constexpr const mapping_type& mapping() const noexcept { return map_; }
3398a4dda33SDimitry Andric    constexpr const accessor_type& accessor() const noexcept { return acc_; }
3408a4dda33SDimitry Andric
3415f757f3fSDimitry Andric    // per LWG-4021 "mdspan::is_always_meow() should be noexcept"
3425f757f3fSDimitry Andric    static constexpr bool is_always_unique() noexcept
3438a4dda33SDimitry Andric      { return mapping_type::is_always_unique(); }
3445f757f3fSDimitry Andric    static constexpr bool is_always_exhaustive() noexcept
3458a4dda33SDimitry Andric      { return mapping_type::is_always_exhaustive(); }
3465f757f3fSDimitry Andric    static constexpr bool is_always_strided() noexcept
3478a4dda33SDimitry Andric      { return mapping_type::is_always_strided(); }
3488a4dda33SDimitry Andric
3498a4dda33SDimitry Andric    constexpr bool is_unique() const
3508a4dda33SDimitry Andric      { return map_.is_unique(); }
3518a4dda33SDimitry Andric    constexpr bool is_exhaustive() const
3528a4dda33SDimitry Andric      { return map_.is_exhaustive(); }
3538a4dda33SDimitry Andric    constexpr bool is_strided() const
3548a4dda33SDimitry Andric      { return map_.is_strided(); }
3558a4dda33SDimitry Andric    constexpr index_type stride(rank_type r) const
3568a4dda33SDimitry Andric      { return map_.stride(r); }
3578a4dda33SDimitry Andric
3588a4dda33SDimitry Andric  private:
3598a4dda33SDimitry Andric    accessor_type acc_;         // exposition only
3608a4dda33SDimitry Andric    mapping_type map_;          // exposition only
3618a4dda33SDimitry Andric    data_handle_type ptr_;      // exposition only
3628a4dda33SDimitry Andric  };
3638a4dda33SDimitry Andric
3648a4dda33SDimitry Andric  template<class CArray>
3658a4dda33SDimitry Andric    requires(is_array_v<CArray> && rank_v<CArray> == 1)
3668a4dda33SDimitry Andric    mdspan(CArray&)
3678a4dda33SDimitry Andric      -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;
3688a4dda33SDimitry Andric
3698a4dda33SDimitry Andric  template<class Pointer>
3708a4dda33SDimitry Andric    requires(is_pointer_v<remove_reference_t<Pointer>>)
3718a4dda33SDimitry Andric    mdspan(Pointer&&)
3728a4dda33SDimitry Andric      -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
3738a4dda33SDimitry Andric
3748a4dda33SDimitry Andric  template<class ElementType, class... Integrals>
3758a4dda33SDimitry Andric    requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
3768a4dda33SDimitry Andric    explicit mdspan(ElementType*, Integrals...)
377*0fca6ea1SDimitry Andric      -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;            // until C++26
378*0fca6ea1SDimitry Andric  template<class ElementType, class... Integrals>
379*0fca6ea1SDimitry Andric    requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
380*0fca6ea1SDimitry Andric    explicit mdspan(ElementType*, Integrals...)
381*0fca6ea1SDimitry Andric      -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>;  // since C++26
3828a4dda33SDimitry Andric
3838a4dda33SDimitry Andric  template<class ElementType, class OtherIndexType, size_t N>
3848a4dda33SDimitry Andric    mdspan(ElementType*, span<OtherIndexType, N>)
3858a4dda33SDimitry Andric      -> mdspan<ElementType, dextents<size_t, N>>;
3868a4dda33SDimitry Andric
3878a4dda33SDimitry Andric  template<class ElementType, class OtherIndexType, size_t N>
3888a4dda33SDimitry Andric    mdspan(ElementType*, const array<OtherIndexType, N>&)
3898a4dda33SDimitry Andric      -> mdspan<ElementType, dextents<size_t, N>>;
3908a4dda33SDimitry Andric
3918a4dda33SDimitry Andric  template<class ElementType, class IndexType, size_t... ExtentsPack>
3928a4dda33SDimitry Andric    mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)
3938a4dda33SDimitry Andric      -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;
3948a4dda33SDimitry Andric
3958a4dda33SDimitry Andric  template<class ElementType, class MappingType>
3968a4dda33SDimitry Andric    mdspan(ElementType*, const MappingType&)
3978a4dda33SDimitry Andric      -> mdspan<ElementType, typename MappingType::extents_type,
3988a4dda33SDimitry Andric                typename MappingType::layout_type>;
3998a4dda33SDimitry Andric
4008a4dda33SDimitry Andric  template<class MappingType, class AccessorType>
4018a4dda33SDimitry Andric    mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
4028a4dda33SDimitry Andric           const AccessorType&)
4038a4dda33SDimitry Andric      -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
4048a4dda33SDimitry Andric                typename MappingType::layout_type, AccessorType>;
4058a4dda33SDimitry Andric}
40606c3fb27SDimitry Andric*/
40706c3fb27SDimitry Andric
40806c3fb27SDimitry Andric#ifndef _LIBCPP_MDSPAN
40906c3fb27SDimitry Andric#define _LIBCPP_MDSPAN
41006c3fb27SDimitry Andric
41106c3fb27SDimitry Andric#include <__config>
412*0fca6ea1SDimitry Andric
413*0fca6ea1SDimitry Andric#if _LIBCPP_STD_VER >= 23
41406c3fb27SDimitry Andric#  include <__fwd/mdspan.h>
41506c3fb27SDimitry Andric#  include <__mdspan/default_accessor.h>
41606c3fb27SDimitry Andric#  include <__mdspan/extents.h>
41706c3fb27SDimitry Andric#  include <__mdspan/layout_left.h>
41806c3fb27SDimitry Andric#  include <__mdspan/layout_right.h>
4195f757f3fSDimitry Andric#  include <__mdspan/layout_stride.h>
4208a4dda33SDimitry Andric#  include <__mdspan/mdspan.h>
421*0fca6ea1SDimitry Andric#endif
422*0fca6ea1SDimitry Andric
4235f757f3fSDimitry Andric#include <version>
42406c3fb27SDimitry Andric
42506c3fb27SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
42606c3fb27SDimitry Andric#  pragma GCC system_header
42706c3fb27SDimitry Andric#endif
42806c3fb27SDimitry Andric
429*0fca6ea1SDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
430*0fca6ea1SDimitry Andric#  include <array>
431*0fca6ea1SDimitry Andric#  include <cinttypes>
432*0fca6ea1SDimitry Andric#  include <concepts>
433*0fca6ea1SDimitry Andric#  include <cstddef>
434*0fca6ea1SDimitry Andric#  include <limits>
435*0fca6ea1SDimitry Andric#  include <span>
436*0fca6ea1SDimitry Andric#endif
437*0fca6ea1SDimitry Andric
43806c3fb27SDimitry Andric#endif // _LIBCPP_MDSPAN
439