1 | //===----------------------------------------------------------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 |
10 | |
11 | // <mdspan> |
12 | |
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 |
18 | // |
19 | // the following types and expressions are well-formed and have the specified semantics. |
20 | // |
21 | // typename M::extents_type |
22 | // Result: A type that is a specialization of extents. |
23 | // |
24 | // typename M::index_type |
25 | // Result: typename M::extents_type::index_type. |
26 | // |
27 | // typename M::rank_type |
28 | // Result: typename M::extents_type::rank_type. |
29 | // |
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. |
32 | // |
33 | // m.extents() |
34 | // Result: const typename M::extents_type& |
35 | // |
36 | // m(i...) |
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(). |
39 | // |
40 | // m(i...) == m(static_cast<typename M::index_type>(i)...) |
41 | // Result: bool |
42 | // Returns: true |
43 | // |
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. |
47 | // |
48 | // m.is_unique() |
49 | // Result: bool |
50 | // Returns: true only if for every i and j where (i != j || ...) is true, m(i...) != m(j...) is true. |
51 | // |
52 | // m.is_exhaustive() |
53 | // Result: bool |
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. |
55 | // |
56 | // m.is_strided() |
57 | // Result: bool |
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 |
61 | // |
62 | // m.stride(r) |
63 | // Preconditions: m.is_strided() is true. |
64 | // Result: typename M::index_type |
65 | // Returns: sr as defined in m.is_strided() above. |
66 | // |
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. |
70 | // |
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. |
74 | // |
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. |
78 | |
79 | #include <mdspan> |
80 | #include <type_traits> |
81 | #include <concepts> |
82 | #include <cassert> |
83 | |
84 | #include "test_macros.h" |
85 | |
86 | // Common requirements of all layout mappings |
87 | template <class M, size_t... Idxs> |
88 | void test_mapping_requirements(std::index_sequence<Idxs...>) { |
89 | using E = typename M::extents_type; |
90 | LIBCPP_STATIC_ASSERT(std::__mdspan_detail::__is_extents_v<E>); |
91 | static_assert(std::is_copy_constructible_v<M>); |
92 | static_assert(std::is_nothrow_move_constructible_v<M>); |
93 | static_assert(std::is_nothrow_move_assignable_v<M>); |
94 | static_assert(std::is_nothrow_swappable_v<M>); |
95 | ASSERT_SAME_TYPE(typename M::index_type, typename E::index_type); |
96 | ASSERT_SAME_TYPE(typename M::size_type, typename E::size_type); |
97 | ASSERT_SAME_TYPE(typename M::rank_type, typename E::rank_type); |
98 | ASSERT_SAME_TYPE(typename M::layout_type, std::layout_right); |
99 | ASSERT_SAME_TYPE(typename M::layout_type::template mapping<E>, M); |
100 | static_assert(std::is_same_v<decltype(std::declval<M>().extents()), const E&>); |
101 | static_assert(std::is_same_v<decltype(std::declval<M>()(Idxs...)), typename M::index_type>); |
102 | static_assert(std::is_same_v<decltype(std::declval<M>().required_span_size()), typename M::index_type>); |
103 | static_assert(std::is_same_v<decltype(std::declval<M>().is_unique()), bool>); |
104 | static_assert(std::is_same_v<decltype(std::declval<M>().is_exhaustive()), bool>); |
105 | static_assert(std::is_same_v<decltype(std::declval<M>().is_strided()), bool>); |
106 | if constexpr (E::rank() > 0) |
107 | static_assert(std::is_same_v<decltype(std::declval<M>().stride(0)), typename M::index_type>); |
108 | static_assert(std::is_same_v<decltype(M::is_always_unique()), bool>); |
109 | static_assert(std::is_same_v<decltype(M::is_always_exhaustive()), bool>); |
110 | static_assert(std::is_same_v<decltype(M::is_always_strided()), bool>); |
111 | } |
112 | |
113 | template <class L, class E> |
114 | void test_layout_mapping_requirements() { |
115 | using M = typename L::template mapping<E>; |
116 | test_mapping_requirements<M>(std::make_index_sequence<E::rank()>()); |
117 | } |
118 | |
119 | template <class E> |
120 | void test_layout_mapping_right() { |
121 | test_layout_mapping_requirements<std::layout_right, E>(); |
122 | } |
123 | |
124 | int main(int, char**) { |
125 | constexpr size_t D = std::dynamic_extent; |
126 | test_layout_mapping_right<std::extents<int>>(); |
127 | test_layout_mapping_right<std::extents<signed char, 4, 5>>(); |
128 | test_layout_mapping_right<std::extents<unsigned, D, 4>>(); |
129 | test_layout_mapping_right<std::extents<size_t, D, D, D, D>>(); |
130 | return 0; |
131 | } |
132 | |