1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
13 // A type M meets the layout mapping requirements if
14 // - M models copyable and equality_comparable,
15 // - is_nothrow_move_constructible_v<M> is true,
16 // - is_nothrow_move_assignable_v<M> is true,
17 // - is_nothrow_swappable_v<M> is true, and
19 // the following types and expressions are well-formed and have the specified semantics.
21 // typename M::extents_type
22 // Result: A type that is a specialization of extents.
24 // typename M::index_type
25 // Result: typename M::extents_type::index_type.
27 // typename M::rank_type
28 // Result: typename M::extents_type::rank_type.
30 // typename M::layout_type
31 // Result: A type MP that meets the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) and for which is-mapping-of<MP, M> is true.
34 // Result: const typename M::extents_type&
37 // Result: typename M::index_type
38 // Returns: A nonnegative integer less than numeric_limits<typename M::index_type>::max() and less than or equal to numeric_limits<size_t>::max().
40 // m(i...) == m(static_cast<typename M::index_type>(i)...)
44 // m.required_span_size()
45 // Result: typename M::index_type
46 // 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.
50 // Returns: true only if for every i and j where (i != j || ...) is true, m(i...) != m(j...) is true.
54 // 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.
58 // Returns: true only if for every rank index r of m.extents() there exists an integer
59 // sr such that, for all i where (i+dr) is a multidimensional index in m.extents() ([mdspan.overview]),
60 // m((i + dr)...) - m(i...) equals sr
63 // Preconditions: m.is_strided() is true.
64 // Result: typename M::index_type
65 // Returns: sr as defined in m.is_strided() above.
67 // M::is_always_unique()
68 // Result: A constant expression ([expr.const]) of type bool.
69 // Returns: true only if m.is_unique() is true for all possible objects m of type M.
71 // M::is_always_exhaustive()
72 // Result: A constant expression ([expr.const]) of type bool.
73 // Returns: true only if m.is_exhaustive() is true for all possible objects m of type M.
75 // M::is_always_strided()
76 // Result: A constant expression ([expr.const]) of type bool.
77 // Returns: true only if m.is_strided() is true for all possible objects m of type M.
82 #include <span> // dynamic_extent
83 #include <type_traits>
86 #include "test_macros.h"
88 // Common requirements of all layout mappings
89 template <class M
, size_t... Idxs
>
90 void test_mapping_requirements(std::index_sequence
<Idxs
...>) {
91 using E
= typename
M::extents_type
;
92 LIBCPP_STATIC_ASSERT(std::__mdspan_detail::__is_extents_v
<E
>);
93 static_assert(std::is_copy_constructible_v
<M
>);
94 static_assert(std::is_nothrow_move_constructible_v
<M
>);
95 static_assert(std::is_nothrow_move_assignable_v
<M
>);
96 static_assert(std::is_nothrow_swappable_v
<M
>);
97 ASSERT_SAME_TYPE(typename
M::index_type
, typename
E::index_type
);
98 ASSERT_SAME_TYPE(typename
M::size_type
, typename
E::size_type
);
99 ASSERT_SAME_TYPE(typename
M::rank_type
, typename
E::rank_type
);
100 ASSERT_SAME_TYPE(typename
M::layout_type
, std::layout_right
);
101 ASSERT_SAME_TYPE(typename
M::layout_type::template mapping
<E
>, M
);
102 static_assert(std::is_same_v
<decltype(std::declval
<M
>().extents()), const E
&>);
103 static_assert(std::is_same_v
<decltype(std::declval
<M
>()(Idxs
...)), typename
M::index_type
>);
104 static_assert(std::is_same_v
<decltype(std::declval
<M
>().required_span_size()), typename
M::index_type
>);
105 static_assert(std::is_same_v
<decltype(std::declval
<M
>().is_unique()), bool>);
106 static_assert(std::is_same_v
<decltype(std::declval
<M
>().is_exhaustive()), bool>);
107 static_assert(std::is_same_v
<decltype(std::declval
<M
>().is_strided()), bool>);
108 if constexpr (E::rank() > 0)
109 static_assert(std::is_same_v
<decltype(std::declval
<M
>().stride(0)), typename
M::index_type
>);
110 static_assert(std::is_same_v
<decltype(M::is_always_unique()), bool>);
111 static_assert(std::is_same_v
<decltype(M::is_always_exhaustive()), bool>);
112 static_assert(std::is_same_v
<decltype(M::is_always_strided()), bool>);
115 template <class L
, class E
>
116 void test_layout_mapping_requirements() {
117 using M
= typename
L::template mapping
<E
>;
118 test_mapping_requirements
<M
>(std::make_index_sequence
<E::rank()>());
122 void test_layout_mapping_right() {
123 test_layout_mapping_requirements
<std::layout_right
, E
>();
126 int main(int, char**) {
127 constexpr size_t D
= std::dynamic_extent
;
128 test_layout_mapping_right
<std::extents
<int>>();
129 test_layout_mapping_right
<std::extents
<signed char, 4, 5>>();
130 test_layout_mapping_right
<std::extents
<unsigned, D
, 4>>();
131 test_layout_mapping_right
<std::extents
<size_t, D
, D
, D
, D
>>();