1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
13 // template<class OtherIndexType>
14 // constexpr mapping(const extents_type& e, span<OtherIndexType, rank_> s) noexcept;
17 // - is_convertible_v<const OtherIndexType&, index_type> is true, and
18 // - is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
21 // - s[i] > 0 is true for all i in the range [0, rank_).
22 // - REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]).
23 // - If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_),
24 // such that s[pi] >= s[pi_1] * e.extent(pi_1) is true for all i in the range [1, rank_), where pi is the ith element of P.
25 // Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true.
27 // Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_),
28 // direct-non-list-initializes strides_[d] with as_const(s[d]).
35 #include <span> // dynamic_extent
36 #include <type_traits>
38 #include "test_macros.h"
39 #include "../ConvertibleToIntegral.h"
41 template <class E
, class S
>
42 constexpr void test_construction(E e
, S s
) {
43 using M
= std::layout_stride::mapping
<E
>;
44 ASSERT_NOEXCEPT(M
{e
, s
});
47 // check correct extents are returned
48 ASSERT_NOEXCEPT(m
.extents());
49 assert(m
.extents() == e
);
51 // check required_span_size()
52 typename
E::index_type expected_size
= 1;
53 for (typename
E::rank_type r
= 0; r
< E::rank(); r
++) {
54 if (e
.extent(r
) == 0) {
58 expected_size
+= (e
.extent(r
) - 1) * static_cast<typename
E::index_type
>(s
[r
]);
60 assert(m
.required_span_size() == expected_size
);
62 // check strides: node stride function is constrained on rank>0, e.extent(r) is not
63 auto strides
= m
.strides();
64 ASSERT_NOEXCEPT(m
.strides());
65 if constexpr (E::rank() > 0) {
66 for (typename
E::rank_type r
= 0; r
< E::rank(); r
++) {
67 assert(m
.stride(r
) == static_cast<typename
E::index_type
>(s
[r
]));
68 assert(strides
[r
] == m
.stride(r
));
73 constexpr bool test() {
74 constexpr size_t D
= std::dynamic_extent
;
76 std::array
<int, 0> s
{};
77 test_construction(std::extents
<int>(), std::span(s
));
80 std::array
<int, 1> s
{1};
81 test_construction(std::extents
<unsigned, D
>(7), std::span(s
));
84 std::array
<int, 1> s
{1};
85 test_construction(std::extents
<unsigned, D
>(0), std::span(s
));
88 std::array
<int, 1> s
{2};
89 test_construction(std::extents
<unsigned, 7>(), std::span(s
));
92 std::array
<IntType
, 1> s
{1};
93 test_construction(std::extents
<int, D
>(7), std::span(s
));
96 std::array
<int, 2> s
{3, 30};
97 test_construction(std::extents
<unsigned, 7, 8>(), std::span(s
));
100 std::array
<int, 4> s
{20, 2, 200, 2000};
101 test_construction(std::extents
<int64_t, D
, 8, D
, D
>(7, 9, 10), std::span(s
));
104 std::array
<int, 4> s
{20, 2, 200, 2000};
105 test_construction(std::extents
<int64_t, D
, 8, D
, D
>(7, 0, 10), std::span(s
));
106 test_construction(std::extents
<int64_t, D
, 8, D
, D
>(0, 9, 10), std::span(s
));
107 test_construction(std::extents
<int64_t, D
, 8, D
, D
>(0, 8, 0), std::span(s
));
110 std::array
<int, 4> s
{200, 20, 20, 2000};
111 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 0, 8, 9), std::span(s
));
112 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 8, 0, 9), std::span(s
));
113 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 1, 8, 9), std::span(s
));
114 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 8, 1, 9), std::span(s
));
115 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 1, 1, 9), std::span(s
));
116 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 0, 0, 9), std::span(s
));
117 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 1, 1, 9), std::span(s
));
118 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 1, 0, 9), std::span(s
));
119 test_construction(std::extents
<int64_t, D
, D
, D
, D
>(7, 0, 1, 9), std::span(s
));
123 using mapping_t
= std::layout_stride::mapping
<std::dextents
<unsigned, 2>>;
124 // wrong strides size
125 static_assert(!std::is_constructible_v
<mapping_t
, std::dextents
<int, 2>, std::span
<int, 3>>);
126 static_assert(!std::is_constructible_v
<mapping_t
, std::dextents
<int, 2>, std::span
<int, 1>>);
127 // wrong extents rank
128 static_assert(!std::is_constructible_v
<mapping_t
, std::dextents
<int, 3>, std::span
<int, 2>>);
129 // none-convertible strides
130 static_assert(!std::is_constructible_v
<mapping_t
, std::dextents
<int, 2>, std::span
<IntType
, 2>>);
133 // not no-throw constructible index_type from stride
134 using mapping_t
= std::layout_stride::mapping
<std::dextents
<unsigned char, 2>>;
135 static_assert(std::is_convertible_v
<IntType
, unsigned char>);
136 static_assert(!std::is_constructible_v
<mapping_t
, std::dextents
<int, 2>, std::span
<IntType
, 2>>);
141 int main(int, char**) {
143 static_assert(test());