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