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 <span> // dynamic_extent 83 #include <type_traits> 84 #include <utility> 85 86 #include "test_macros.h" 87 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>); 113 } 114 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()>()); 119 } 120 121 template <class E> 122 void test_layout_mapping_right() { 123 test_layout_mapping_requirements<std::layout_right, E>(); 124 } 125 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>>(); 132 return 0; 133 } 134