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
9
10 // <span>
11
12 // template<size_t Offset, size_t Count = dynamic_extent>
13 // constexpr span<element_type, see below> subspan() const;
14 //
15 // constexpr span<element_type, dynamic_extent> subspan(
16 // size_type offset, size_type count = dynamic_extent) const;
17 //
18 // Requires: (0 <= Offset && Offset <= size())
19 // && (Count == dynamic_extent || Count >= 0 && Offset + Count <= size())
20
21 #include <span>
22 #include <cassert>
23 #include <algorithm>
24 #include <string>
25
26 #include "test_macros.h"
27
28 template <typename Span, size_t Offset, size_t Count>
testConstexprSpan(Span sp)29 constexpr bool testConstexprSpan(Span sp)
30 {
31 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>())));
32 LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count))));
33 auto s1 = sp.template subspan<Offset, Count>();
34 auto s2 = sp.subspan(Offset, Count);
35 using S1 = decltype(s1);
36 using S2 = decltype(s2);
37 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
38 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
39 static_assert(S1::extent == Count);
40 static_assert(S2::extent == std::dynamic_extent, "");
41 return
42 s1.data() == s2.data()
43 && s1.size() == s2.size()
44 && std::equal(s1.begin(), s1.end(), sp.begin() + Offset);
45 }
46
47 template <typename Span, size_t Offset>
testConstexprSpan(Span sp)48 constexpr bool testConstexprSpan(Span sp)
49 {
50 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>())));
51 LIBCPP_ASSERT((noexcept(sp.subspan(Offset))));
52 auto s1 = sp.template subspan<Offset>();
53 auto s2 = sp.subspan(Offset);
54 using S1 = decltype(s1);
55 using S2 = decltype(s2);
56 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
57 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
58 static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), "");
59 static_assert(S2::extent == std::dynamic_extent, "");
60 return
61 s1.data() == s2.data()
62 && s1.size() == s2.size()
63 && std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end());
64 }
65
66
67 template <typename Span, size_t Offset, size_t Count>
testRuntimeSpan(Span sp)68 void testRuntimeSpan(Span sp)
69 {
70 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>())));
71 LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count))));
72 auto s1 = sp.template subspan<Offset, Count>();
73 auto s2 = sp.subspan(Offset, Count);
74 using S1 = decltype(s1);
75 using S2 = decltype(s2);
76 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
77 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
78 static_assert(S1::extent == Count);
79 static_assert(S2::extent == std::dynamic_extent, "");
80 assert(s1.data() == s2.data());
81 assert(s1.size() == s2.size());
82 assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset));
83 }
84
85
86 template <typename Span, size_t Offset>
testRuntimeSpan(Span sp)87 void testRuntimeSpan(Span sp)
88 {
89 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>())));
90 LIBCPP_ASSERT((noexcept(sp.subspan(Offset))));
91 auto s1 = sp.template subspan<Offset>();
92 auto s2 = sp.subspan(Offset);
93 using S1 = decltype(s1);
94 using S2 = decltype(s2);
95 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
96 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
97 static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), "");
98 static_assert(S2::extent == std::dynamic_extent, "");
99 assert(s1.data() == s2.data());
100 assert(s1.size() == s2.size());
101 assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end()));
102 }
103
104
105 constexpr int carr1[] = {1,2,3,4};
106 int arr1[] = {5,6,7};
107
main(int,char **)108 int main(int, char**)
109 {
110 {
111 using Sp = std::span<const int>;
112 static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
113
114 static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), "");
115 static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), "");
116 static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), "");
117 static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), "");
118 static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), "");
119
120 static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), "");
121 static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), "");
122 static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), "");
123 static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), "");
124 }
125
126 {
127 using Sp = std::span<const int, 4>;
128
129 static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), "");
130 static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), "");
131 static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), "");
132 static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), "");
133 static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), "");
134
135 static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), "");
136 static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), "");
137 static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), "");
138 static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), "");
139 }
140
141 {
142 using Sp = std::span<const int>;
143 static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
144
145 static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
146 static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
147 static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
148 static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
149 static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
150 }
151
152 {
153 using Sp = std::span<const int, 4>;
154
155 static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
156
157 static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
158 static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
159 static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
160 static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
161 }
162
163 {
164 using Sp = std::span<int>;
165 testRuntimeSpan<Sp, 0>(Sp{});
166
167 testRuntimeSpan<Sp, 0, 3>(Sp{arr1});
168 testRuntimeSpan<Sp, 0, 2>(Sp{arr1});
169 testRuntimeSpan<Sp, 0, 1>(Sp{arr1});
170 testRuntimeSpan<Sp, 0, 0>(Sp{arr1});
171
172 testRuntimeSpan<Sp, 1, 2>(Sp{arr1});
173 testRuntimeSpan<Sp, 2, 1>(Sp{arr1});
174 testRuntimeSpan<Sp, 3, 0>(Sp{arr1});
175 }
176
177 {
178 using Sp = std::span<int, 3>;
179
180 testRuntimeSpan<Sp, 0, 3>(Sp{arr1});
181 testRuntimeSpan<Sp, 0, 2>(Sp{arr1});
182 testRuntimeSpan<Sp, 0, 1>(Sp{arr1});
183 testRuntimeSpan<Sp, 0, 0>(Sp{arr1});
184
185 testRuntimeSpan<Sp, 1, 2>(Sp{arr1});
186 testRuntimeSpan<Sp, 2, 1>(Sp{arr1});
187 testRuntimeSpan<Sp, 3, 0>(Sp{arr1});
188 }
189
190 {
191 using Sp = std::span<int>;
192 testRuntimeSpan<Sp, 0>(Sp{});
193
194 testRuntimeSpan<Sp, 0>(Sp{arr1});
195 testRuntimeSpan<Sp, 1>(Sp{arr1});
196 testRuntimeSpan<Sp, 2>(Sp{arr1});
197 testRuntimeSpan<Sp, 3>(Sp{arr1});
198 }
199
200 {
201 using Sp = std::span<int, 3>;
202
203 testRuntimeSpan<Sp, 0>(Sp{arr1});
204 testRuntimeSpan<Sp, 1>(Sp{arr1});
205 testRuntimeSpan<Sp, 2>(Sp{arr1});
206 testRuntimeSpan<Sp, 3>(Sp{arr1});
207 }
208
209 return 0;
210 }
211