xref: /llvm-project/libcxx/test/std/containers/views/views.span/span.sub/subspan.pass.cpp (revision fb855eb941b6d740cc6560297d0b4d3201dcaf9f)
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