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