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