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