| 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 <cassert> |
| 80 | #include <cstddef> |
| 81 | #include <mdspan> |
| 82 | #include <type_traits> |
| 83 | #include <utility> |
| 84 | |
| 85 | #include "test_macros.h" |
| 86 | |
| 87 | // Common requirements of all layout mappings |
| 88 | template <class M, size_t... Idxs> |
| 89 | void test_mapping_requirements(std::index_sequence<Idxs...>) { |
| 90 | using E = typename M::extents_type; |
| 91 | LIBCPP_STATIC_ASSERT(std::__mdspan_detail::__is_extents_v<E>); |
| 92 | static_assert(std::is_copy_constructible_v<M>); |
| 93 | static_assert(std::is_nothrow_move_constructible_v<M>); |
| 94 | static_assert(std::is_nothrow_move_assignable_v<M>); |
| 95 | static_assert(std::is_nothrow_swappable_v<M>); |
| 96 | ASSERT_SAME_TYPE(typename M::index_type, typename E::index_type); |
| 97 | ASSERT_SAME_TYPE(typename M::size_type, typename E::size_type); |
| 98 | ASSERT_SAME_TYPE(typename M::rank_type, typename E::rank_type); |
| 99 | ASSERT_SAME_TYPE(typename M::layout_type, std::layout_right); |
| 100 | ASSERT_SAME_TYPE(typename M::layout_type::template mapping<E>, M); |
| 101 | static_assert(std::is_same_v<decltype(std::declval<M>().extents()), const E&>); |
| 102 | static_assert(std::is_same_v<decltype(std::declval<M>()(Idxs...)), typename M::index_type>); |
| 103 | static_assert(std::is_same_v<decltype(std::declval<M>().required_span_size()), typename M::index_type>); |
| 104 | static_assert(std::is_same_v<decltype(std::declval<M>().is_unique()), bool>); |
| 105 | static_assert(std::is_same_v<decltype(std::declval<M>().is_exhaustive()), bool>); |
| 106 | static_assert(std::is_same_v<decltype(std::declval<M>().is_strided()), bool>); |
| 107 | if constexpr (E::rank() > 0) |
| 108 | static_assert(std::is_same_v<decltype(std::declval<M>().stride(0)), typename M::index_type>); |
| 109 | static_assert(std::is_same_v<decltype(M::is_always_unique()), bool>); |
| 110 | static_assert(std::is_same_v<decltype(M::is_always_exhaustive()), bool>); |
| 111 | static_assert(std::is_same_v<decltype(M::is_always_strided()), bool>); |
| 112 | } |
| 113 | |
| 114 | template <class L, class E> |
| 115 | void test_layout_mapping_requirements() { |
| 116 | using M = typename L::template mapping<E>; |
| 117 | test_mapping_requirements<M>(std::make_index_sequence<E::rank()>()); |
| 118 | } |
| 119 | |
| 120 | template <class E> |
| 121 | void test_layout_mapping_right() { |
| 122 | test_layout_mapping_requirements<std::layout_right, E>(); |
| 123 | } |
| 124 | |
| 125 | int main(int, char**) { |
| 126 | constexpr size_t D = std::dynamic_extent; |
| 127 | test_layout_mapping_right<std::extents<int>>(); |
| 128 | test_layout_mapping_right<std::extents<signed char, 4, 5>>(); |
| 129 | test_layout_mapping_right<std::extents<unsigned, D, 4>>(); |
| 130 | test_layout_mapping_right<std::extents<size_t, D, D, D, D>>(); |
| 131 | return 0; |
| 132 | } |
| 133 | |