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 // Test default iteration: 14 // 15 // template<class... Indices> 16 // constexpr index_type operator()(Indices...) const noexcept; 17 // 18 // Constraints: 19 // * sizeof...(Indices) == extents_type::rank() is true, 20 // * (is_convertible_v<Indices, index_type> && ...) is true, and 21 // * (is_nothrow_constructible_v<index_type, Indices> && ...) is true. 22 // 23 // Preconditions: 24 // * extents_type::index-cast(i) is a multidimensional index in extents_. 25 26 #include <cassert> 27 #include <cstddef> 28 #include <cstdint> 29 #include <mdspan> 30 #include <span> // dynamic_extent 31 #include <type_traits> 32 33 #include "test_macros.h" 34 35 #include "../ConvertibleToIntegral.h" 36 37 template<class Mapping, class ... Indices> 38 concept operator_constraints = requires(Mapping m, Indices ... idxs) { 39 {std::is_same_v<decltype(m(idxs...)), typename Mapping::index_type>}; 40 }; 41 42 template<class Mapping, class ... Indices> 43 requires( 44 operator_constraints<Mapping, Indices...> 45 ) 46 constexpr bool check_operator_constraints(Mapping m, Indices ... idxs) { 47 (void) m(idxs...); 48 return true; 49 } 50 51 template<class Mapping, class ... Indices> 52 constexpr bool check_operator_constraints(Mapping, Indices ...) { 53 return false; 54 } 55 56 template <class M, class T, class... Args> 57 constexpr void iterate_right(M m, T& count, Args... args) { 58 constexpr size_t r = sizeof...(Args); 59 if constexpr (M::extents_type::rank() == r) { 60 ASSERT_NOEXCEPT(m(args...)); 61 assert(count == m(args...)); 62 count++; 63 } else { 64 for (typename M::index_type i = 0; i < m.extents().extent(r); i++) { 65 iterate_right(m, count, args..., i); 66 } 67 } 68 } 69 70 template <class E, class... Args> 71 constexpr void test_iteration(Args... args) { 72 using M = std::layout_right::mapping<E>; 73 M m(E(args...)); 74 75 typename E::index_type count = 0; 76 iterate_right(m, count); 77 } 78 79 constexpr bool test() { 80 constexpr size_t D = std::dynamic_extent; 81 test_iteration<std::extents<int>>(); 82 test_iteration<std::extents<unsigned, D>>(1); 83 test_iteration<std::extents<unsigned, D>>(7); 84 test_iteration<std::extents<unsigned, 7>>(); 85 test_iteration<std::extents<unsigned, 7, 8>>(); 86 test_iteration<std::extents<signed char, D, D, D, D>>(1, 1, 1, 1); 87 88 // Check operator constraint for number of arguments 89 static_assert(check_operator_constraints(std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(1)), 0)); 90 static_assert(!check_operator_constraints(std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(1)), 0, 0)); 91 92 // Check operator constraint for convertibility of arguments to index_type 93 static_assert(check_operator_constraints(std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(1)), IntType(0))); 94 static_assert(!check_operator_constraints(std::layout_right::mapping<std::extents<unsigned, D>>(std::extents<unsigned, D>(1)), IntType(0))); 95 96 // Check operator constraint for no-throw-constructibility of index_type from arguments 97 static_assert(!check_operator_constraints(std::layout_right::mapping<std::extents<unsigned char, D>>(std::extents<unsigned char, D>(1)), IntType(0))); 98 99 return true; 100 } 101 102 constexpr bool test_large() { 103 constexpr size_t D = std::dynamic_extent; 104 test_iteration<std::extents<int64_t, D, 8, D, D>>(7, 9, 10); 105 test_iteration<std::extents<int64_t, D, 8, 1, D>>(7, 10); 106 return true; 107 } 108 109 int main(int, char**) { 110 test(); 111 static_assert(test()); 112 113 // The large test iterates over ~10k loop indices. 114 // With assertions enabled this triggered the maximum default limit 115 // for steps in consteval expressions. Assertions roughly double the 116 // total number of instructions, so this was already close to the maximum. 117 test_large(); 118 return 0; 119 } 120