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 | // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 |
9 | |
10 | // <mdspan> |
11 | |
12 | #include <array> |
13 | #include <cassert> |
14 | #include <cstddef> |
15 | #include <mdspan> |
16 | #include <span> |
17 | |
18 | #include "../ConvertibleToIntegral.h" |
19 | #include "test_macros.h" |
20 | |
21 | // Helper file to implement combinatorial testing of extents constructor |
22 | // |
23 | // std::extents can be constructed from just indices, a std::array, or a std::span |
24 | // In each of those cases one can either provide all extents, or just the dynamic ones |
25 | // If constructed from std::span, the span needs to have a static extent |
26 | // Furthermore, the indices/array/span can have integer types other than index_type |
27 | |
28 | template <class E, class AllExtents> |
29 | constexpr void test_runtime_observers(E ext, AllExtents expected) { |
30 | for (typename E::rank_type r = 0; r < ext.rank(); r++) { |
31 | ASSERT_SAME_TYPE(decltype(ext.extent(0)), typename E::index_type); |
32 | ASSERT_NOEXCEPT(ext.extent(0)); |
33 | assert(ext.extent(r) == static_cast<typename E::index_type>(expected[r])); |
34 | } |
35 | } |
36 | |
37 | template <class E, class AllExtents> |
38 | constexpr void test_implicit_construction_call(E e, AllExtents all_ext) { |
39 | test_runtime_observers(e, all_ext); |
40 | } |
41 | |
42 | template <class E, class Test, class AllExtents> |
43 | constexpr void test_construction(AllExtents all_ext) { |
44 | // test construction from all extents |
45 | Test::template test_construction<E>(all_ext, all_ext, std::make_index_sequence<E::rank()>()); |
46 | |
47 | // test construction from just dynamic extents |
48 | // create an array of just the extents corresponding to dynamic values |
49 | std::array<typename AllExtents::value_type, E::rank_dynamic()> dyn_ext{}; |
50 | size_t dynamic_idx = 0; |
51 | for (size_t r = 0; r < E::rank(); r++) { |
52 | if (E::static_extent(r) == std::dynamic_extent) { |
53 | dyn_ext[dynamic_idx] = all_ext[r]; |
54 | dynamic_idx++; |
55 | } |
56 | } |
57 | Test::template test_construction<E>(all_ext, dyn_ext, std::make_index_sequence<E::rank_dynamic()>()); |
58 | } |
59 | |
60 | template <class T, class TArg, class Test> |
61 | constexpr void test() { |
62 | constexpr size_t D = std::dynamic_extent; |
63 | |
64 | test_construction<std::extents<T>, Test>(std::array<TArg, 0>{}); |
65 | |
66 | test_construction<std::extents<T, 3>, Test>(std::array<TArg, 1>{3}); |
67 | test_construction<std::extents<T, D>, Test>(std::array<TArg, 1>{3}); |
68 | |
69 | test_construction<std::extents<T, 3, 7>, Test>(std::array<TArg, 2>{3, 7}); |
70 | test_construction<std::extents<T, 3, D>, Test>(std::array<TArg, 2>{3, 7}); |
71 | test_construction<std::extents<T, D, 7>, Test>(std::array<TArg, 2>{3, 7}); |
72 | test_construction<std::extents<T, D, D>, Test>(std::array<TArg, 2>{3, 7}); |
73 | |
74 | test_construction<std::extents<T, 3, 7, 9>, Test>(std::array<TArg, 3>{3, 7, 9}); |
75 | test_construction<std::extents<T, 3, 7, D>, Test>(std::array<TArg, 3>{3, 7, 9}); |
76 | test_construction<std::extents<T, 3, D, D>, Test>(std::array<TArg, 3>{3, 7, 9}); |
77 | test_construction<std::extents<T, D, 7, D>, Test>(std::array<TArg, 3>{3, 7, 9}); |
78 | test_construction<std::extents<T, D, D, D>, Test>(std::array<TArg, 3>{3, 7, 9}); |
79 | test_construction<std::extents<T, 3, D, 9>, Test>(std::array<TArg, 3>{3, 7, 9}); |
80 | test_construction<std::extents<T, D, D, 9>, Test>(std::array<TArg, 3>{3, 7, 9}); |
81 | test_construction<std::extents<T, D, 7, 9>, Test>(std::array<TArg, 3>{3, 7, 9}); |
82 | |
83 | test_construction<std::extents<T, 1, 2, 3, 4, 5, 6, 7, 8, 9>, Test>(std::array<TArg, 9>{1, 2, 3, 4, 5, 6, 7, 8, 9}); |
84 | test_construction<std::extents<T, D, 2, 3, D, 5, D, 7, D, 9>, Test>(std::array<TArg, 9>{1, 2, 3, 4, 5, 6, 7, 8, 9}); |
85 | test_construction<std::extents<T, D, D, D, D, D, D, D, D, D>, Test>(std::array<TArg, 9>{1, 2, 3, 4, 5, 6, 7, 8, 9}); |
86 | } |
87 | |
88 | template <class Test> |
89 | constexpr bool test_index_type_combo() { |
90 | test<int, int, Test>(); |
91 | test<int, size_t, Test>(); |
92 | test<unsigned, int, Test>(); |
93 | test<signed char, size_t, Test>(); |
94 | test<long long, unsigned, Test>(); |
95 | test<size_t, int, Test>(); |
96 | test<size_t, size_t, Test>(); |
97 | test<int, IntType, Test>(); |
98 | test<signed char, IntType, Test>(); |
99 | return true; |
100 | } |
101 | |