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 //  constexpr span& operator=(const span& other) noexcept = default;
13 
14 #include <span>
15 #include <cassert>
16 #include <string>
17 #include <utility>
18 
19 #include "test_macros.h"
20 
21 template <typename T>
22 constexpr bool doAssign(T lhs, T rhs)
23 {
24     ASSERT_NOEXCEPT(std::declval<T&>() = rhs);
25     lhs = rhs;
26     return lhs.data() == rhs.data()
27      &&    lhs.size() == rhs.size();
28 }
29 
30 struct A{};
31 
32 constexpr int carr1[] = {1,2,3,4};
33 constexpr int carr2[] = {3,4,5};
34 constexpr int carr3[] = {7,8};
35           int   arr[] = {5,6,7,9};
36 std::string strs[] = {"ABC", "DEF", "GHI"};
37 
38 
39 int main(int, char**)
40 {
41 
42 //  constexpr dynamically sized assignment
43     {
44 //  On systems where 'ptrdiff_t' is a synonym for 'int',
45 //  the call span(ptr, 0) selects the (pointer, size_type) constructor.
46 //  On systems where 'ptrdiff_t' is NOT a synonym for 'int',
47 //  it is ambiguous, because of 0 also being convertible to a null pointer
48 //  and so the compiler can't choose between:
49 //      span(pointer, size_type)
50 //  and span(pointer, pointer)
51 //  We cast zero to std::ptrdiff_t to remove that ambiguity.
52 //  Example:
53 //      On darwin x86_64, ptrdiff_t is the same as long int.
54 //      On darwin i386, ptrdiff_t is the same as int.
55         constexpr std::span<const int> spans[] = {
56             {},
57             {carr1, static_cast<std::size_t>(0)},
58             {carr1,     1U},
59             {carr1,     2U},
60             {carr1,     3U},
61             {carr1,     4U},
62             {carr2, static_cast<std::size_t>(0)},
63             {carr2,     1U},
64             {carr2,     2U},
65             {carr2,     3U},
66             {carr3, static_cast<std::size_t>(0)},
67             {carr3,     1U},
68             {carr3,     2U}
69             };
70 
71         static_assert(std::size(spans) == 13, "" );
72 
73 //  No for loops in constexpr land :-(
74         static_assert(doAssign(spans[0], spans[0]), "");
75         static_assert(doAssign(spans[0], spans[1]), "");
76         static_assert(doAssign(spans[0], spans[2]), "");
77         static_assert(doAssign(spans[0], spans[3]), "");
78         static_assert(doAssign(spans[0], spans[4]), "");
79         static_assert(doAssign(spans[0], spans[5]), "");
80         static_assert(doAssign(spans[0], spans[6]), "");
81         static_assert(doAssign(spans[0], spans[7]), "");
82         static_assert(doAssign(spans[0], spans[8]), "");
83         static_assert(doAssign(spans[0], spans[9]), "");
84         static_assert(doAssign(spans[0], spans[10]), "");
85         static_assert(doAssign(spans[0], spans[11]), "");
86         static_assert(doAssign(spans[0], spans[12]), "");
87 
88         static_assert(doAssign(spans[1], spans[1]), "");
89         static_assert(doAssign(spans[1], spans[2]), "");
90         static_assert(doAssign(spans[1], spans[3]), "");
91         static_assert(doAssign(spans[1], spans[4]), "");
92         static_assert(doAssign(spans[1], spans[5]), "");
93         static_assert(doAssign(spans[1], spans[6]), "");
94         static_assert(doAssign(spans[1], spans[7]), "");
95         static_assert(doAssign(spans[1], spans[8]), "");
96         static_assert(doAssign(spans[1], spans[9]), "");
97         static_assert(doAssign(spans[1], spans[10]), "");
98         static_assert(doAssign(spans[1], spans[11]), "");
99         static_assert(doAssign(spans[1], spans[12]), "");
100 
101         static_assert(doAssign(spans[2], spans[2]), "");
102         static_assert(doAssign(spans[2], spans[3]), "");
103         static_assert(doAssign(spans[2], spans[4]), "");
104         static_assert(doAssign(spans[2], spans[5]), "");
105         static_assert(doAssign(spans[2], spans[6]), "");
106         static_assert(doAssign(spans[2], spans[7]), "");
107         static_assert(doAssign(spans[2], spans[8]), "");
108         static_assert(doAssign(spans[2], spans[9]), "");
109         static_assert(doAssign(spans[2], spans[10]), "");
110         static_assert(doAssign(spans[2], spans[11]), "");
111         static_assert(doAssign(spans[2], spans[12]), "");
112 
113         static_assert(doAssign(spans[3], spans[3]), "");
114         static_assert(doAssign(spans[3], spans[4]), "");
115         static_assert(doAssign(spans[3], spans[4]), "");
116         static_assert(doAssign(spans[3], spans[4]), "");
117         static_assert(doAssign(spans[3], spans[4]), "");
118         static_assert(doAssign(spans[3], spans[4]), "");
119         static_assert(doAssign(spans[3], spans[4]), "");
120         static_assert(doAssign(spans[3], spans[4]), "");
121         static_assert(doAssign(spans[3], spans[4]), "");
122         static_assert(doAssign(spans[3], spans[10]), "");
123         static_assert(doAssign(spans[3], spans[11]), "");
124         static_assert(doAssign(spans[3], spans[12]), "");
125 
126         static_assert(doAssign(spans[4], spans[4]), "");
127         static_assert(doAssign(spans[4], spans[5]), "");
128         static_assert(doAssign(spans[4], spans[6]), "");
129         static_assert(doAssign(spans[4], spans[7]), "");
130         static_assert(doAssign(spans[4], spans[8]), "");
131         static_assert(doAssign(spans[4], spans[9]), "");
132         static_assert(doAssign(spans[4], spans[10]), "");
133         static_assert(doAssign(spans[4], spans[11]), "");
134         static_assert(doAssign(spans[4], spans[12]), "");
135 
136         static_assert(doAssign(spans[5], spans[5]), "");
137         static_assert(doAssign(spans[5], spans[6]), "");
138         static_assert(doAssign(spans[5], spans[7]), "");
139         static_assert(doAssign(spans[5], spans[8]), "");
140         static_assert(doAssign(spans[5], spans[9]), "");
141         static_assert(doAssign(spans[5], spans[10]), "");
142         static_assert(doAssign(spans[5], spans[11]), "");
143         static_assert(doAssign(spans[5], spans[12]), "");
144 
145         static_assert(doAssign(spans[6], spans[6]), "");
146         static_assert(doAssign(spans[6], spans[7]), "");
147         static_assert(doAssign(spans[6], spans[8]), "");
148         static_assert(doAssign(spans[6], spans[9]), "");
149         static_assert(doAssign(spans[6], spans[10]), "");
150         static_assert(doAssign(spans[6], spans[11]), "");
151         static_assert(doAssign(spans[6], spans[12]), "");
152 
153         static_assert(doAssign(spans[7], spans[7]), "");
154         static_assert(doAssign(spans[7], spans[8]), "");
155         static_assert(doAssign(spans[7], spans[9]), "");
156         static_assert(doAssign(spans[7], spans[10]), "");
157         static_assert(doAssign(spans[7], spans[11]), "");
158         static_assert(doAssign(spans[7], spans[12]), "");
159 
160         static_assert(doAssign(spans[8], spans[8]), "");
161         static_assert(doAssign(spans[8], spans[9]), "");
162         static_assert(doAssign(spans[8], spans[10]), "");
163         static_assert(doAssign(spans[8], spans[11]), "");
164         static_assert(doAssign(spans[8], spans[12]), "");
165 
166         static_assert(doAssign(spans[9], spans[9]), "");
167         static_assert(doAssign(spans[9], spans[10]), "");
168         static_assert(doAssign(spans[9], spans[11]), "");
169         static_assert(doAssign(spans[9], spans[12]), "");
170 
171         static_assert(doAssign(spans[10], spans[10]), "");
172         static_assert(doAssign(spans[10], spans[11]), "");
173         static_assert(doAssign(spans[10], spans[12]), "");
174 
175         static_assert(doAssign(spans[11], spans[11]), "");
176         static_assert(doAssign(spans[11], spans[12]), "");
177 
178         static_assert(doAssign(spans[12], spans[12]), "");
179 
180 //      for (size_t i = 0; i < std::size(spans); ++i)
181 //          for (size_t j = i; j < std::size(spans); ++j)
182 //              static_assert(doAssign(spans[i], spans[j]), "");
183     }
184 
185 //  constexpr statically sized assignment
186     {
187         using spanType = std::span<const int,2>;
188         constexpr spanType spans[] = {
189             spanType{carr1, 2},
190             spanType{carr1 + 1, 2},
191             spanType{carr1 + 2, 2},
192             spanType{carr2, 2},
193             spanType{carr2 + 1, 2},
194             spanType{carr3, 2}
195             };
196 
197         static_assert(std::size(spans) == 6, "" );
198 
199 //  No for loops in constexpr land :-(
200         static_assert(doAssign(spans[0], spans[0]), "");
201         static_assert(doAssign(spans[0], spans[1]), "");
202         static_assert(doAssign(spans[0], spans[2]), "");
203         static_assert(doAssign(spans[0], spans[3]), "");
204         static_assert(doAssign(spans[0], spans[4]), "");
205         static_assert(doAssign(spans[0], spans[5]), "");
206 
207         static_assert(doAssign(spans[1], spans[1]), "");
208         static_assert(doAssign(spans[1], spans[2]), "");
209         static_assert(doAssign(spans[1], spans[3]), "");
210         static_assert(doAssign(spans[1], spans[4]), "");
211         static_assert(doAssign(spans[1], spans[5]), "");
212 
213         static_assert(doAssign(spans[2], spans[2]), "");
214         static_assert(doAssign(spans[2], spans[3]), "");
215         static_assert(doAssign(spans[2], spans[4]), "");
216         static_assert(doAssign(spans[2], spans[5]), "");
217 
218         static_assert(doAssign(spans[3], spans[3]), "");
219         static_assert(doAssign(spans[3], spans[4]), "");
220         static_assert(doAssign(spans[3], spans[5]), "");
221 
222         static_assert(doAssign(spans[4], spans[4]), "");
223         static_assert(doAssign(spans[4], spans[5]), "");
224 
225         static_assert(doAssign(spans[5], spans[5]), "");
226 
227 //      for (size_t i = 0; i < std::size(spans); ++i)
228 //          for (size_t j = i; j < std::size(spans); ++j)
229 //              static_assert(doAssign(spans[i], spans[j]), "");
230     }
231 
232 
233 //  dynamically sized assignment
234     {
235         std::span<int> spans[] = {
236             {},
237             {arr,     arr + 1},
238             {arr,     arr + 2},
239             {arr,     arr + 3},
240             {arr + 1, arr + 3} // same size as s2
241             };
242 
243         for (size_t i = 0; i < std::size(spans); ++i)
244             for (size_t j = i; j < std::size(spans); ++j)
245                 assert((doAssign(spans[i], spans[j])));
246     }
247 
248 //  statically sized assignment
249     {
250         using spanType = std::span<int,2>;
251         spanType spans[] = {
252             spanType{arr,     arr + 2},
253             spanType{arr + 1, arr + 3},
254             spanType{arr + 2, arr + 4}
255             };
256 
257         for (size_t i = 0; i < std::size(spans); ++i)
258             for (size_t j = i; j < std::size(spans); ++j)
259                 assert((doAssign(spans[i], spans[j])));
260     }
261 
262 //  dynamically sized assignment
263     {
264     std::span<std::string> spans[] = {
265             {strs,     strs},
266             {strs,     strs + 1},
267             {strs,     strs + 2},
268             {strs,     strs + 3},
269             {strs + 1, strs + 1},
270             {strs + 1, strs + 2},
271             {strs + 1, strs + 3},
272             {strs + 2, strs + 2},
273             {strs + 2, strs + 3},
274             {strs + 3, strs + 3}
275             };
276 
277         for (size_t i = 0; i < std::size(spans); ++i)
278             for (size_t j = i; j < std::size(spans); ++j)
279                 assert((doAssign(spans[i], spans[j])));
280     }
281 
282     {
283     using spanType = std::span<std::string, 1>;
284     spanType spans[] = {
285             spanType{strs,     strs + 1},
286             spanType{strs + 1, strs + 2},
287             spanType{strs + 2, strs + 3}
288             };
289 
290         for (size_t i = 0; i < std::size(spans); ++i)
291             for (size_t j = i; j < std::size(spans); ++j)
292                 assert((doAssign(spans[i], spans[j])));
293     }
294 
295   return 0;
296 }
297