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
27template <typename Span, std::size_t Offset, size_t Count>
28constexpr bool testConstexprSpan(Span sp) {
29 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>())));
30 LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count))));
31 auto s1 = sp.template subspan<Offset, Count>();
32 auto s2 = sp.subspan(Offset, Count);
33 using S1 = decltype(s1);
34 using S2 = decltype(s2);
35 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
36 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
37 static_assert(S1::extent == Count);
38 static_assert(S2::extent == std::dynamic_extent, "");
39 return s1.data() == s2.data() && s1.size() == s2.size() && std::equal(s1.begin(), s1.end(), sp.begin() + Offset);
40}
41
42template <typename Span, std::size_t Offset>
43constexpr bool testConstexprSpan(Span sp) {
44 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>())));
45 LIBCPP_ASSERT((noexcept(sp.subspan(Offset))));
46 auto s1 = sp.template subspan<Offset>();
47 auto s2 = sp.subspan(Offset);
48 using S1 = decltype(s1);
49 using S2 = decltype(s2);
50 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
51 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
52 static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), "");
53 static_assert(S2::extent == std::dynamic_extent, "");
54 return s1.data() == s2.data() && s1.size() == s2.size() &&
55 std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end());
56}
57
58template <typename Span, std::size_t Offset, size_t Count>
59void testRuntimeSpan(Span sp) {
60 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>())));
61 LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count))));
62 auto s1 = sp.template subspan<Offset, Count>();
63 auto s2 = sp.subspan(Offset, Count);
64 using S1 = decltype(s1);
65 using S2 = decltype(s2);
66 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
67 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
68 static_assert(S1::extent == Count);
69 static_assert(S2::extent == std::dynamic_extent, "");
70 assert(s1.data() == s2.data());
71 assert(s1.size() == s2.size());
72 assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset));
73}
74
75template <typename Span, std::size_t Offset>
76void testRuntimeSpan(Span sp) {
77 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>())));
78 LIBCPP_ASSERT((noexcept(sp.subspan(Offset))));
79 auto s1 = sp.template subspan<Offset>();
80 auto s2 = sp.subspan(Offset);
81 using S1 = decltype(s1);
82 using S2 = decltype(s2);
83 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
84 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
85 static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), "");
86 static_assert(S2::extent == std::dynamic_extent, "");
87 assert(s1.data() == s2.data());
88 assert(s1.size() == s2.size());
89 assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end()));
90}
91
92constexpr int carr1[] = {1, 2, 3, 4};
93int arr1[] = {5, 6, 7};
94
95int main(int, char**) {
96 {
97 using Sp = std::span<const int>;
98 static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
99
100 static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), "");
101 static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), "");
102 static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), "");
103 static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), "");
104 static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), "");
105
106 static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), "");
107 static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), "");
108 static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), "");
109 static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), "");
110 }
111
112 {
113 using Sp = std::span<const int, 4>;
114
115 static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), "");
116 static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), "");
117 static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), "");
118 static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), "");
119 static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), "");
120
121 static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), "");
122 static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), "");
123 static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), "");
124 static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), "");
125 }
126
127 {
128 using Sp = std::span<const int>;
129 static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
130
131 static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
132 static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
133 static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
134 static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
135 static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
136 }
137
138 {
139 using Sp = std::span<const int, 4>;
140
141 static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
142
143 static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
144 static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
145 static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
146 static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
147 }
148
149 {
150 using Sp = std::span<int>;
151 testRuntimeSpan<Sp, 0>(Sp{});
152
153 testRuntimeSpan<Sp, 0, 3>(Sp{arr1});
154 testRuntimeSpan<Sp, 0, 2>(Sp{arr1});
155 testRuntimeSpan<Sp, 0, 1>(Sp{arr1});
156 testRuntimeSpan<Sp, 0, 0>(Sp{arr1});
157
158 testRuntimeSpan<Sp, 1, 2>(Sp{arr1});
159 testRuntimeSpan<Sp, 2, 1>(Sp{arr1});
160 testRuntimeSpan<Sp, 3, 0>(Sp{arr1});
161 }
162
163 {
164 using Sp = std::span<int, 3>;
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>;
178 testRuntimeSpan<Sp, 0>(Sp{});
179
180 testRuntimeSpan<Sp, 0>(Sp{arr1});
181 testRuntimeSpan<Sp, 1>(Sp{arr1});
182 testRuntimeSpan<Sp, 2>(Sp{arr1});
183 testRuntimeSpan<Sp, 3>(Sp{arr1});
184 }
185
186 {
187 using Sp = std::span<int, 3>;
188
189 testRuntimeSpan<Sp, 0>(Sp{arr1});
190 testRuntimeSpan<Sp, 1>(Sp{arr1});
191 testRuntimeSpan<Sp, 2>(Sp{arr1});
192 testRuntimeSpan<Sp, 3>(Sp{arr1});
193 }
194
195 return 0;
196}
197

source code of libcxx/test/std/containers/views/views.span/span.sub/subspan.pass.cpp