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