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