1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
4 //
5 // This code is licensed under the MIT License (MIT).
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
13 // THE SOFTWARE.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #ifdef _MSC_VER
18 // blanket turn off warnings from CppCoreCheck from catch
19 // so people aren't annoyed by them when running the tool.
20 #pragma warning(disable : 26440 26426) // from catch
21
22 #endif
23
24 #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
25
26 #include <gsl/gsl_byte> // for byte
27 #include <gsl/gsl_util> // for narrow_cast
28 #include <gsl/multi_span> // for multi_span, contiguous_span_iterator, dim
29
30 #include <algorithm> // for fill, for_each
31 #include <array> // for array
32 #include <iostream> // for ptrdiff_t, size_t
33 #include <iterator> // for reverse_iterator, begin, end, operator!=
34 #include <numeric> // for iota
35 #include <stddef.h> // for ptrdiff_t
36 #include <string> // for string
37 #include <vector> // for vector
38
39 namespace gsl
40 {
41 struct fail_fast;
42 } // namespace gsl
43
44 using namespace std;
45 using namespace gsl;
46
47 namespace
48 {
49 struct BaseClass
50 {
51 };
52 struct DerivedClass : BaseClass
53 {
54 };
55 } // namespace
56
57 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
58 TEST_CASE("default_constructor")
59 {
60 {
61 multi_span<int> s;
62 CHECK((s.length() == 0 && s.data() == nullptr));
63
64 multi_span<const int> cs;
65 CHECK((cs.length() == 0 && cs.data() == nullptr));
66 }
67
68 {
69 multi_span<int, 0> s;
70 CHECK((s.length() == 0 && s.data() == nullptr));
71
72 multi_span<const int, 0> cs;
73 CHECK((cs.length() == 0 && cs.data() == nullptr));
74 }
75
76 {
77 #ifdef CONFIRM_COMPILATION_ERRORS
78 multi_span<int, 1> s;
79 CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
80 #endif
81 }
82
83 {
84 multi_span<int> s{};
85 CHECK((s.length() == 0 && s.data() == nullptr));
86
87 multi_span<const int> cs{};
88 CHECK((cs.length() == 0 && cs.data() == nullptr));
89 }
90 }
91
92 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
93 TEST_CASE("from_nullptr_constructor")
94 {
95 {
96 multi_span<int> s = nullptr;
97 CHECK((s.length() == 0 && s.data() == nullptr));
98
99 multi_span<const int> cs = nullptr;
100 CHECK((cs.length() == 0 && cs.data() == nullptr));
101 }
102
103 {
104 multi_span<int, 0> s = nullptr;
105 CHECK((s.length() == 0 && s.data() == nullptr));
106
107 multi_span<const int, 0> cs = nullptr;
108 CHECK((cs.length() == 0 && cs.data() == nullptr));
109 }
110
111 {
112 #ifdef CONFIRM_COMPILATION_ERRORS
113 multi_span<int, 1> s = nullptr;
114 CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
115 #endif
116 }
117
118 {
119 multi_span<int> s{nullptr};
120 CHECK((s.length() == 0 && s.data() == nullptr));
121
122 multi_span<const int> cs{nullptr};
123 CHECK((cs.length() == 0 && cs.data() == nullptr));
124 }
125
126 {
127 multi_span<int*> s{nullptr};
128 CHECK((s.length() == 0 && s.data() == nullptr));
129
130 multi_span<const int*> cs{nullptr};
131 CHECK((cs.length() == 0 && cs.data() == nullptr));
132 }
133 }
134
135 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
136 TEST_CASE("from_nullptr_length_constructor") {
137 {
138 multi_span<int> s{nullptr, 0};
139 CHECK((s.length() == 0 && s.data() == nullptr));
140
141 multi_span<const int> cs{nullptr, 0};
142 CHECK((cs.length() == 0 && cs.data() == nullptr));
143 }
144
145 {
146 multi_span<int, 0> s{nullptr, 0};
147 CHECK((s.length() == 0 && s.data() == nullptr));
148
149 multi_span<const int, 0> cs{nullptr, 0};
150 CHECK((cs.length() == 0 && cs.data() == nullptr));
151 }
152
153 {
__anonbe47408a0202() 154 auto workaround_macro = []() { const multi_span<int> s{nullptr, 1}; };
155 CHECK_THROWS_AS(workaround_macro(), fail_fast);
156
__anonbe47408a0302() 157 auto const_workaround_macro = []() { const multi_span<const int> cs{nullptr, 1}; };
158 CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
159 }
160
161 {
__anonbe47408a0402() 162 auto workaround_macro = []() { const multi_span<int, 0> s{nullptr, 1}; };
163 CHECK_THROWS_AS(workaround_macro(), fail_fast);
164
__anonbe47408a0502() 165 auto const_workaround_macro = []() { const multi_span<const int, 0> s{nullptr, 1}; };
166 CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
167 }
168
169 {
170 multi_span<int*> s{nullptr, 0};
171 CHECK((s.length() == 0 && s.data() == nullptr));
172
173 multi_span<const int*> cs{nullptr, 0};
174 CHECK((cs.length() == 0 && cs.data() == nullptr));
175 }
176
177 {
178 #ifdef CONFIRM_COMPILATION_ERRORS
179 multi_span<int, 1> s{nullptr, 0};
180 CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
181 #endif
182 }
183 }
184
185 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
186 TEST_CASE("from_element_constructor")
187 {
188 int i = 5;
189
190 {
191 multi_span<int> s = i;
192 CHECK((s.length() == 1 && s.data() == &i));
193 CHECK(s[0] == 5);
194
195 multi_span<const int> cs = i;
196 CHECK((cs.length() == 1 && cs.data() == &i));
197 CHECK(cs[0] == 5);
198 }
199
200 {
201 #ifdef CONFIRM_COMPILATION_ERRORS
202 const j = 1;
203 multi_span<int, 0> s = j;
204 #endif
205 }
206
207 {
208 #ifdef CONFIRM_COMPILATION_ERRORS
209 multi_span<int, 0> s = i;
210 CHECK((s.length() == 0 && s.data() == &i));
211 #endif
212 }
213
214 {
215 multi_span<int, 1> s = i;
216 CHECK((s.length() == 1 && s.data() == &i));
217 CHECK(s[0] == 5);
218 }
219
220 {
221 #ifdef CONFIRM_COMPILATION_ERRORS
222 multi_span<int, 2> s = i;
223 CHECK((s.length() == 2 && s.data() == &i));
224 #endif
225 }
226
227 {
228 #ifdef CONFIRM_COMPILATION_ERRORS
__anonbe47408a0602() 229 auto get_a_temp = []() -> int { return 4; };
__anonbe47408a0702(multi_span<int> s) 230 auto use_a_span = [](multi_span<int> s) { (void) s; };
231 use_a_span(get_a_temp());
232 #endif
233 }
234 }
235
236 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
237 TEST_CASE("from_pointer_length_constructor")
238 {
239 int arr[4] = {1, 2, 3, 4};
240
241 {
242 multi_span<int> s{&arr[0], 2};
243 CHECK((s.length() == 2 && s.data() == &arr[0]));
244 CHECK((s[0] == 1 && s[1] == 2));
245 }
246
247 {
248 multi_span<int, 2> s{&arr[0], 2};
249 CHECK((s.length() == 2 && s.data() == &arr[0]));
250 CHECK((s[0] == 1 && s[1] == 2));
251 }
252
253 {
254 int* p = nullptr;
255 multi_span<int> s{p, 0};
256 CHECK((s.length() == 0 && s.data() == nullptr));
257 }
258
259 {
260 int* p = nullptr;
__anonbe47408a0802() 261 auto workaround_macro = [=]() { const multi_span<int> s{p, 2}; };
262 CHECK_THROWS_AS(workaround_macro(), fail_fast);
263 }
264 }
265
266 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
267 TEST_CASE("from_pointer_pointer_constructor")
268 {
269 int arr[4] = {1, 2, 3, 4};
270
271 {
272 multi_span<int> s{&arr[0], &arr[2]};
273 CHECK((s.length() == 2 && s.data() == &arr[0]));
274 CHECK((s[0] == 1 && s[1] == 2));
275 }
276
277 {
278 multi_span<int, 2> s{&arr[0], &arr[2]};
279 CHECK((s.length() == 2 && s.data() == &arr[0]));
280 CHECK((s[0] == 1 && s[1] == 2));
281 }
282
283 {
284 multi_span<int> s{&arr[0], &arr[0]};
285 CHECK((s.length() == 0 && s.data() == &arr[0]));
286 }
287
288 {
289 multi_span<int, 0> s{&arr[0], &arr[0]};
290 CHECK((s.length() == 0 && s.data() == &arr[0]));
291 }
292
293 {
__anonbe47408a0902() 294 auto workaround_macro = [&]() { const multi_span<int> s{&arr[1], &arr[0]}; };
295 CHECK_THROWS_AS(workaround_macro(), fail_fast);
296 }
297
298 {
299 int* p = nullptr;
__anonbe47408a0a02() 300 auto workaround_macro = [&]() { const multi_span<int> s{&arr[0], p}; };
301 CHECK_THROWS_AS(workaround_macro(), fail_fast);
302 }
303
304 {
305 int* p = nullptr;
__anonbe47408a0b02() 306 auto workaround_macro = [&]() { const multi_span<int> s{p, p}; };
307 CHECK_THROWS_AS(workaround_macro(), fail_fast);
308 }
309
310 {
311 int* p = nullptr;
__anonbe47408a0c02() 312 auto workaround_macro = [&]() { const multi_span<int> s{&arr[0], p}; };
313 CHECK_THROWS_AS(workaround_macro(), fail_fast);
314 }
315 }
316
317 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
318 GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
319 TEST_CASE("from_array_constructor")
320 {
321 int arr[5] = {1, 2, 3, 4, 5};
322
323 {
324 multi_span<int> s{arr};
325 CHECK((s.length() == 5 && s.data() == &arr[0]));
326 }
327
328 {
329 multi_span<int, 5> s{arr};
330 CHECK((s.length() == 5 && s.data() == &arr[0]));
331 }
332
333 {
334 #ifdef CONFIRM_COMPILATION_ERRORS
335 multi_span<int, 6> s{arr};
336 #endif
337 }
338
339 {
340 multi_span<int, 0> s{arr};
341 CHECK((s.length() == 0 && s.data() == &arr[0]));
342 }
343
344 int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
345
346 {
347 multi_span<int> s{arr2d};
348 CHECK((s.length() == 6 && s.data() == &arr2d[0][0]));
349 CHECK((s[0] == 1 && s[5] == 6));
350 }
351
352 {
353 multi_span<int, 0> s{arr2d};
354 CHECK((s.length() == 0 && s.data() == &arr2d[0][0]));
355 }
356
357 {
358 #ifdef CONFIRM_COMPILATION_ERRORS
359 multi_span<int, 5> s{arr2d};
360 #endif
361 }
362
363 {
364 multi_span<int, 6> s{arr2d};
365 CHECK((s.length() == 6 && s.data() == &arr2d[0][0]));
366 CHECK((s[0] == 1 && s[5] == 6));
367 }
368
369 {
370 #ifdef CONFIRM_COMPILATION_ERRORS
371 multi_span<int, 7> s{arr2d};
372 #endif
373 }
374
375 {
376 multi_span<int[3]> s{arr2d[0]};
377 CHECK((s.length() == 1 && s.data() == &arr2d[0]));
378 }
379
380 {
381 multi_span<int, 2, 3> s{arr2d};
382 CHECK((s.length() == 6 && s.data() == &arr2d[0][0]));
__anonbe47408a0d02() 383 auto workaround_macro = [&]() { return s[{1, 2}] == 6; };
384 CHECK(workaround_macro());
385 }
386
387 {
388 #ifdef CONFIRM_COMPILATION_ERRORS
389 multi_span<int, 3, 3> s{arr2d};
390 #endif
391 }
392
393 int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
394
395 {
396 multi_span<int> s{arr3d};
397 CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0]));
398 CHECK((s[0] == 1 && s[11] == 12));
399 }
400
401 {
402 multi_span<int, 0> s{arr3d};
403 CHECK((s.length() == 0 && s.data() == &arr3d[0][0][0]));
404 }
405
406 {
407 #ifdef CONFIRM_COMPILATION_ERRORS
408 multi_span<int, 11> s{arr3d};
409 #endif
410 }
411
412 {
413 multi_span<int, 12> s{arr3d};
414 CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0]));
415 CHECK((s[0] == 1 && s[5] == 6));
416 }
417
418 {
419 #ifdef CONFIRM_COMPILATION_ERRORS
420 multi_span<int, 13> s{arr3d};
421 #endif
422 }
423
424 {
425 multi_span<int[3][2]> s{arr3d[0]};
426 CHECK((s.length() == 1 && s.data() == &arr3d[0]));
427 }
428
429 {
430 multi_span<int, 3, 2, 2> s{arr3d};
431 CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0]));
__anonbe47408a0e02() 432 auto workaround_macro = [&]() { return s[{2, 1, 0}] == 11; };
433 CHECK(workaround_macro());
434 }
435
436 {
437 #ifdef CONFIRM_COMPILATION_ERRORS
438 multi_span<int, 3, 3, 3> s{arr3d};
439 #endif
440 }
441 }
442
443 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
444 GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
445 GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
446 GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
447 GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
448 TEST_CASE("from_dynamic_array_constructor")
449 {
450 double(*arr)[3][4] = new double[100][3][4];
451
452 {
453 multi_span<double, dynamic_range, 3, 4> s(arr, 10);
454 CHECK((s.length() == 120 && s.data() == &arr[0][0][0]));
455 CHECK_THROWS_AS(s[10][3][4], fail_fast);
456 }
457
458 {
459 multi_span<double, dynamic_range, 4, 3> s(arr, 10);
460 CHECK((s.length() == 120 && s.data() == &arr[0][0][0]));
461 }
462
463 {
464 multi_span<double> s(arr, 10);
465 CHECK((s.length() == 120 && s.data() == &arr[0][0][0]));
466 }
467
468 {
469 multi_span<double, dynamic_range, 3, 4> s(arr, 0);
470 CHECK((s.length() == 0 && s.data() == &arr[0][0][0]));
471 }
472
473 delete[] arr;
474 }
475
476 GSL_SUPPRESS(con.4) // NO-FORMAT: Attribute
477 TEST_CASE("from_std_array_constructor")
478 {
479 std::array<int, 4> arr = {1, 2, 3, 4};
480
481 {
482 multi_span<int> s{arr};
483 CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()));
484
485 multi_span<const int> cs{arr};
486 CHECK((cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data()));
487 }
488
489 {
490 multi_span<int, 4> s{arr};
491 CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()));
492
493 multi_span<const int, 4> cs{arr};
494 CHECK((cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data()));
495 }
496
497 {
498 multi_span<int, 2> s{arr};
499 CHECK((s.size() == 2 && s.data() == arr.data()));
500
501 multi_span<const int, 2> cs{arr};
502 CHECK((cs.size() == 2 && cs.data() == arr.data()));
503 }
504
505 {
506 multi_span<int, 0> s{arr};
507 CHECK((s.size() == 0 && s.data() == arr.data()));
508
509 multi_span<const int, 0> cs{arr};
510 CHECK((cs.size() == 0 && cs.data() == arr.data()));
511 }
512
513 // TODO This is currently an unsupported scenario. We will come back to it as we revise
514 // the multidimensional interface and what transformations between dimensionality look like
515 //{
516 // multi_span<int, 2, 2> s{arr};
517 // CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data());
518 //}
519
520 {
521 #ifdef CONFIRM_COMPILATION_ERRORS
522 multi_span<int, 5> s{arr};
523 #endif
524 }
525
526 {
527 #ifdef CONFIRM_COMPILATION_ERRORS
__anonbe47408a0f02() 528 auto get_an_array = []() { return std::array<int, 4>{1, 2, 3, 4}; };
__anonbe47408a1002(multi_span<int> s) 529 auto take_a_span = [](multi_span<int> s) { (void) s; };
530 // try to take a temporary std::array
531 take_a_span(get_an_array());
532 #endif
533 }
534 }
535
536 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
537 TEST_CASE("from_const_std_array_constructor")
538 {
539 const std::array<int, 4> arr = {1, 2, 3, 4};
540
541 {
542 multi_span<const int> s{arr};
543 CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()));
544 }
545
546 {
547 multi_span<const int, 4> s{arr};
548 CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()));
549 }
550
551 {
552 multi_span<const int, 2> s{arr};
553 CHECK((s.size() == 2 && s.data() == arr.data()));
554 }
555
556 {
557 multi_span<const int, 0> s{arr};
558 CHECK((s.size() == 0 && s.data() == arr.data()));
559 }
560
561 // TODO This is currently an unsupported scenario. We will come back to it as we revise
562 // the multidimensional interface and what transformations between dimensionality look like
563 //{
564 // multi_span<int, 2, 2> s{arr};
565 // CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data());
566 //}
567
568 {
569 #ifdef CONFIRM_COMPILATION_ERRORS
570 multi_span<const int, 5> s{arr};
571 #endif
572 }
573
574 {
575 #ifdef CONFIRM_COMPILATION_ERRORS
__anonbe47408a1102() 576 auto get_an_array = []() -> const std::array<int, 4> { return {1, 2, 3, 4}; };
__anonbe47408a1202(multi_span<const int> s) 577 auto take_a_span = [](multi_span<const int> s) { (void) s; };
578 // try to take a temporary std::array
579 take_a_span(get_an_array());
580 #endif
581 }
582 }
583
584 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
585 TEST_CASE("from_container_constructor")
586 {
587 std::vector<int> v = {1, 2, 3};
588 const std::vector<int> cv = v;
589
590 {
591 multi_span<int> s{v};
592 CHECK((s.size() == narrow_cast<std::ptrdiff_t>(v.size()) && s.data() == v.data()));
593
594 multi_span<const int> cs{v};
595 CHECK((cs.size() == narrow_cast<std::ptrdiff_t>(v.size()) && cs.data() == v.data()));
596 }
597
598 std::string str = "hello";
599 const std::string cstr = "hello";
600
601 {
602 #ifdef CONFIRM_COMPILATION_ERRORS
603 multi_span<char> s{str};
604 CHECK((s.size() == narrow_cast<std::ptrdiff_t>(str.size()) && s.data() == str.data()));
605 #endif
606 multi_span<const char> cs{str};
607 CHECK((cs.size() == narrow_cast<std::ptrdiff_t>(str.size()) && cs.data() == str.data()));
608 }
609
610 {
611 #ifdef CONFIRM_COMPILATION_ERRORS
612 multi_span<char> s{cstr};
613 #endif
614 multi_span<const char> cs{cstr};
615 CHECK((cs.size() == narrow_cast<std::ptrdiff_t>(cstr.size()) && cs.data() == cstr.data()));
616 }
617
618 {
619 #ifdef CONFIRM_COMPILATION_ERRORS
__anonbe47408a1302() 620 auto get_temp_vector = []() -> std::vector<int> { return {}; };
__anonbe47408a1402(multi_span<int> s) 621 auto use_span = [](multi_span<int> s) { (void) s; };
622 use_span(get_temp_vector());
623 #endif
624 }
625
626 {
627 #ifdef CONFIRM_COMPILATION_ERRORS
__anonbe47408a1502() 628 auto get_temp_string = []() -> std::string { return {}; };
__anonbe47408a1602(multi_span<char> s) 629 auto use_span = [](multi_span<char> s) { (void) s; };
630 use_span(get_temp_string());
631 #endif
632 }
633
634 {
635 #ifdef CONFIRM_COMPILATION_ERRORS
__anonbe47408a1702() 636 auto get_temp_vector = []() -> const std::vector<int> { return {}; };
__anonbe47408a1802(multi_span<const char> s) 637 auto use_span = [](multi_span<const char> s) { (void) s; };
638 use_span(get_temp_vector());
639 #endif
640 }
641
642 {
643 #ifdef CONFIRM_COMPILATION_ERRORS
__anonbe47408a1902() 644 auto get_temp_string = []() -> const std::string { return {}; };
__anonbe47408a1a02(multi_span<const char> s) 645 auto use_span = [](multi_span<const char> s) { (void) s; };
646 use_span(get_temp_string());
647 #endif
648 }
649
650 {
651 #ifdef CONFIRM_COMPILATION_ERRORS
652 std::map<int, int> m;
653 multi_span<int> s{m};
654 #endif
655 }
656 }
657
658 GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
659 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
660 TEST_CASE("from_convertible_span_constructor")
661 {
662 #ifdef CONFIRM_COMPILATION_ERRORS
663 multi_span<int, 7, 4, 2> av1(nullptr, b1);
664
__anonbe47408a1b02() 665 auto f = [&]() { multi_span<int, 7, 4, 2> av1(nullptr); };
666 CHECK_THROWS_AS(f(), fail_fast);
667 #endif
668
669 #ifdef CONFIRM_COMPILATION_ERRORS
670 static_bounds<std::size_t, 7, dynamic_range, 2> b12(b11);
671 b12 = b11;
672 b11 = b12;
673
674 multi_span<int, dynamic_range> av1 = nullptr;
675 multi_span<int, 7, dynamic_range, 2> av2(av1);
676 multi_span<int, 7, 4, 2> av2(av1);
677 #endif
678
679 multi_span<DerivedClass> avd;
680 #ifdef CONFIRM_COMPILATION_ERRORS
681 multi_span<BaseClass> avb = avd;
682 #endif
683 multi_span<const DerivedClass> avcd = avd;
684 (void) avcd;
685 }
686
687 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
688 TEST_CASE("copy_move_and_assignment")
689 {
690 multi_span<int> s1;
691 CHECK(s1.empty());
692
693 int arr[] = {3, 4, 5};
694
695 multi_span<const int> s2 = arr;
696 CHECK((s2.length() == 3 && s2.data() == &arr[0]));
697
698 s2 = s1;
699 CHECK(s2.empty());
700
__anonbe47408a1c02() 701 auto get_temp_span = [&]() -> multi_span<int> { return {&arr[1], 2}; };
__anonbe47408a1d02(multi_span<const int> s) 702 auto use_span = [&](multi_span<const int> s) {
703 CHECK((s.length() == 2 && s.data() == &arr[1]));
704 };
705 use_span(get_temp_span());
706
707 s1 = get_temp_span();
708 CHECK((s1.length() == 2 && s1.data() == &arr[1]));
709 }
710
711 template <class Bounds>
fn(const Bounds &)712 void fn(const Bounds&)
713 {
714 static_assert(Bounds::static_size == 60, "static bounds is wrong size");
715 }
716
717 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
718 TEST_CASE("as_multi_span_reshape")
719 {
720 int a[3][4][5];
721 auto av = as_multi_span(a);
722 fn(av.bounds());
723 auto av2 = as_multi_span(av, dim<60>());
724 auto av3 = as_multi_span(av2, dim<3>(), dim<4>(), dim<5>());
725 auto av4 = as_multi_span(av3, dim<4>(), dim(3), dim<5>());
726 auto av5 = as_multi_span(av4, dim<3>(), dim<4>(), dim<5>());
727 auto av6 = as_multi_span(av5, dim<12>(), dim(5));
728
729 fill(av6.begin(), av6.end(), 1);
730
731 auto av7 = as_bytes(av6);
732
733 auto av8 = as_multi_span<int>(av7);
734
735 CHECK(av8.size() == av6.size());
736 for (auto i = 0; i < av8.size(); i++) { CHECK(av8[i] == 1); }
737 }
738
739 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
740 TEST_CASE("first")
741 {
742 int arr[5] = {1, 2, 3, 4, 5};
743
744 {
745 multi_span<int, 5> av = arr;
746 CHECK((av.first<2>().bounds() == static_bounds<2>()));
747 CHECK(av.first<2>().length() == 2);
748 CHECK(av.first(2).length() == 2);
749 }
750
751 {
752 multi_span<int, 5> av = arr;
753 CHECK((av.first<0>().bounds() == static_bounds<0>()));
754 CHECK(av.first<0>().length() == 0);
755 CHECK(av.first(0).length() == 0);
756 }
757
758 {
759 multi_span<int, 5> av = arr;
760 CHECK((av.first<5>().bounds() == static_bounds<5>()));
761 CHECK(av.first<5>().length() == 5);
762 CHECK(av.first(5).length() == 5);
763 }
764
765 {
766 multi_span<int, 5> av = arr;
767 #ifdef CONFIRM_COMPILATION_ERRORS
768 CHECK(av.first<6>().bounds() == static_bounds<6>());
769 CHECK(av.first<6>().length() == 6);
770 CHECK(av.first<-1>().length() == -1);
771 #endif
772 CHECK_THROWS_AS(av.first(6).length(), fail_fast);
773 }
774
775 {
776 multi_span<int, dynamic_range> av;
777 CHECK((av.first<0>().bounds() == static_bounds<0>()));
778 CHECK(av.first<0>().length() == 0);
779 CHECK(av.first(0).length() == 0);
780 }
781 }
782
783 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
784 TEST_CASE("last")
785 {
786 int arr[5] = {1, 2, 3, 4, 5};
787
788 {
789 multi_span<int, 5> av = arr;
790 CHECK((av.last<2>().bounds() == static_bounds<2>()));
791 CHECK(av.last<2>().length() == 2);
792 CHECK(av.last(2).length() == 2);
793 }
794
795 {
796 multi_span<int, 5> av = arr;
797 CHECK((av.last<0>().bounds() == static_bounds<0>()));
798 CHECK(av.last<0>().length() == 0);
799 CHECK(av.last(0).length() == 0);
800 }
801
802 {
803 multi_span<int, 5> av = arr;
804 CHECK((av.last<5>().bounds() == static_bounds<5>()));
805 CHECK(av.last<5>().length() == 5);
806 CHECK(av.last(5).length() == 5);
807 }
808
809 {
810 multi_span<int, 5> av = arr;
811 #ifdef CONFIRM_COMPILATION_ERRORS
812 CHECK((av.last<6>().bounds() == static_bounds<6>()));
813 CHECK(av.last<6>().length() == 6);
814 #endif
815 CHECK_THROWS_AS(av.last(6).length(), fail_fast);
816 }
817
818 {
819 multi_span<int, dynamic_range> av;
820 CHECK((av.last<0>().bounds() == static_bounds<0>()));
821 CHECK(av.last<0>().length() == 0);
822 CHECK(av.last(0).length() == 0);
823 }
824 }
825
826 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
827 TEST_CASE("subspan")
828 {
829 int arr[5] = {1, 2, 3, 4, 5};
830
831 {
832 multi_span<int, 5> av = arr;
833 CHECK((av.subspan<2, 2>().bounds() == static_bounds<2>()));
834 CHECK((av.subspan<2, 2>().length() == 2));
835 CHECK(av.subspan(2, 2).length() == 2);
836 CHECK(av.subspan(2, 3).length() == 3);
837 }
838
839 {
840 multi_span<int, 5> av = arr;
841 CHECK((av.subspan<0, 0>().bounds() == static_bounds<0>()));
842 CHECK((av.subspan<0, 0>().length() == 0));
843 CHECK(av.subspan(0, 0).length() == 0);
844 }
845
846 {
847 multi_span<int, 5> av = arr;
848 CHECK((av.subspan<0, 5>().bounds() == static_bounds<5>()));
849 CHECK((av.subspan<0, 5>().length() == 5));
850 CHECK(av.subspan(0, 5).length() == 5);
851 CHECK_THROWS_AS(av.subspan(0, 6).length(), fail_fast);
852 CHECK_THROWS_AS(av.subspan(1, 5).length(), fail_fast);
853 }
854
855 {
856 multi_span<int, 5> av = arr;
857 CHECK((av.subspan<5, 0>().bounds() == static_bounds<0>()));
858 CHECK((av.subspan<5, 0>().length() == 0));
859 CHECK(av.subspan(5, 0).length() == 0);
860 CHECK_THROWS_AS(av.subspan(6, 0).length(), fail_fast);
861 }
862
863 {
864 multi_span<int, dynamic_range> av;
865 CHECK((av.subspan<0, 0>().bounds() == static_bounds<0>()));
866 CHECK((av.subspan<0, 0>().length() == 0));
867 CHECK(av.subspan(0, 0).length() == 0);
868 CHECK_THROWS_AS((av.subspan<1, 0>().length()), fail_fast);
869 }
870
871 {
872 multi_span<int> av;
873 CHECK(av.subspan(0).length() == 0);
874 CHECK_THROWS_AS(av.subspan(1).length(), fail_fast);
875 }
876
877 {
878 multi_span<int> av = arr;
879 CHECK(av.subspan(0).length() == 5);
880 CHECK(av.subspan(1).length() == 4);
881 CHECK(av.subspan(4).length() == 1);
882 CHECK(av.subspan(5).length() == 0);
883 CHECK_THROWS_AS(av.subspan(6).length(), fail_fast);
884 auto av2 = av.subspan(1);
885 for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2);
886 }
887
888 {
889 multi_span<int, 5> av = arr;
890 CHECK(av.subspan(0).length() == 5);
891 CHECK(av.subspan(1).length() == 4);
892 CHECK(av.subspan(4).length() == 1);
893 CHECK(av.subspan(5).length() == 0);
894 CHECK_THROWS_AS(av.subspan(6).length(), fail_fast);
895 auto av2 = av.subspan(1);
896 for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2);
897 }
898 }
899
900 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
901 TEST_CASE("rank")
902 {
903 int arr[2] = {1, 2};
904
905 {
906 multi_span<int> s;
907 CHECK(s.rank() == 1);
908 }
909
910 {
911 multi_span<int, 2> s = arr;
912 CHECK(s.rank() == 1);
913 }
914
915 int arr2d[1][1] = {};
916 {
917 multi_span<int, 1, 1> s = arr2d;
918 CHECK(s.rank() == 2);
919 }
920 }
921
922 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
923 TEST_CASE("extent")
924 {
925 {
926 multi_span<int> s;
927 CHECK(s.extent() == 0);
928 CHECK(s.extent(0) == 0);
929 CHECK_THROWS_AS(s.extent(1), fail_fast);
930 #ifdef CONFIRM_COMPILATION_ERRORS
931 CHECK(s.extent<1>() == 0);
932 #endif
933 }
934
935 {
936 multi_span<int, 0> s;
937 CHECK(s.extent() == 0);
938 CHECK(s.extent(0) == 0);
939 CHECK_THROWS_AS(s.extent(1), fail_fast);
940 }
941
942 {
943 int arr2d[1][2] = {};
944
945 multi_span<int, 1, 2> s = arr2d;
946 CHECK(s.extent() == 1);
947 CHECK(s.extent<0>() == 1);
948 CHECK(s.extent<1>() == 2);
949 CHECK(s.extent(0) == 1);
950 CHECK(s.extent(1) == 2);
951 CHECK_THROWS_AS(s.extent(3), fail_fast);
952 }
953
954 {
955 int arr2d[1][2] = {};
956
957 multi_span<int, 0, 2> s = arr2d;
958 CHECK(s.extent() == 0);
959 CHECK(s.extent<0>() == 0);
960 CHECK(s.extent<1>() == 2);
961 CHECK(s.extent(0) == 0);
962 CHECK(s.extent(1) == 2);
963 CHECK_THROWS_AS(s.extent(3), fail_fast);
964 }
965 }
966
967 TEST_CASE("operator_function_call")
968 {
969 int arr[4] = {1, 2, 3, 4};
970
971 {
972 multi_span<int> s = arr;
973 CHECK(s(0) == 1);
974 CHECK_THROWS_AS(s(5), fail_fast);
975 }
976
977 int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
978
979 {
980 multi_span<int, 2, 3> s = arr2d;
981 CHECK(s(0, 0) == 1);
982 CHECK(s(0, 1) == 2);
983 CHECK(s(1, 2) == 6);
984 }
985
986 int arr3d[2][2][2] = {1, 2, 3, 4, 5, 6, 7, 8};
987
988 {
989 multi_span<int, 2, 2, 2> s = arr3d;
990 CHECK(s(0, 0, 0) == 1);
991 CHECK(s(1, 1, 1) == 8);
992 }
993 }
994
995 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
996 TEST_CASE("comparison_operators")
997 {
998 {
999 int arr[10][2];
1000 auto s1 = as_multi_span(arr);
1001 multi_span<const int, dynamic_range, 2> s2 = s1;
1002
1003 CHECK(s1 == s2);
1004
1005 multi_span<int, 20> s3 = as_multi_span(s1, dim(20));
1006 CHECK((s3 == s2 && s3 == s1));
1007 }
1008
1009 {
1010 multi_span<int> s1 = nullptr;
1011 multi_span<int> s2 = nullptr;
1012 CHECK(s1 == s2);
1013 CHECK(!(s1 != s2));
1014 CHECK(!(s1 < s2));
1015 CHECK(s1 <= s2);
1016 CHECK(!(s1 > s2));
1017 CHECK(s1 >= s2);
1018 CHECK(s2 == s1);
1019 CHECK(!(s2 != s1));
1020 CHECK(!(s2 < s1));
1021 CHECK(s2 <= s1);
1022 CHECK(!(s2 > s1));
1023 CHECK(s2 >= s1);
1024 }
1025
1026 {
1027 int arr[] = {2, 1}; // bigger
1028
1029 multi_span<int> s1 = nullptr;
1030 multi_span<int> s2 = arr;
1031
1032 CHECK(s1 != s2);
1033 CHECK(s2 != s1);
1034 CHECK(!(s1 == s2));
1035 CHECK(!(s2 == s1));
1036 CHECK(s1 < s2);
1037 CHECK(!(s2 < s1));
1038 CHECK(s1 <= s2);
1039 CHECK(!(s2 <= s1));
1040 CHECK(s2 > s1);
1041 CHECK(!(s1 > s2));
1042 CHECK(s2 >= s1);
1043 CHECK(!(s1 >= s2));
1044 }
1045
1046 {
1047 int arr1[] = {1, 2};
1048 int arr2[] = {1, 2};
1049 multi_span<int> s1 = arr1;
1050 multi_span<int> s2 = arr2;
1051
1052 CHECK(s1 == s2);
1053 CHECK(!(s1 != s2));
1054 CHECK(!(s1 < s2));
1055 CHECK(s1 <= s2);
1056 CHECK(!(s1 > s2));
1057 CHECK(s1 >= s2);
1058 CHECK(s2 == s1);
1059 CHECK(!(s2 != s1));
1060 CHECK(!(s2 < s1));
1061 CHECK(s2 <= s1);
1062 CHECK(!(s2 > s1));
1063 CHECK(s2 >= s1);
1064 }
1065
1066 {
1067 int arr[] = {1, 2, 3};
1068
1069 multi_span<int> s1 = {&arr[0], 2}; // shorter
1070 multi_span<int> s2 = arr; // longer
1071
1072 CHECK(s1 != s2);
1073 CHECK(s2 != s1);
1074 CHECK(!(s1 == s2));
1075 CHECK(!(s2 == s1));
1076 CHECK(s1 < s2);
1077 CHECK(!(s2 < s1));
1078 CHECK(s1 <= s2);
1079 CHECK(!(s2 <= s1));
1080 CHECK(s2 > s1);
1081 CHECK(!(s1 > s2));
1082 CHECK(s2 >= s1);
1083 CHECK(!(s1 >= s2));
1084 }
1085
1086 {
1087 int arr1[] = {1, 2}; // smaller
1088 int arr2[] = {2, 1}; // bigger
1089
1090 multi_span<int> s1 = arr1;
1091 multi_span<int> s2 = arr2;
1092
1093 CHECK(s1 != s2);
1094 CHECK(s2 != s1);
1095 CHECK(!(s1 == s2));
1096 CHECK(!(s2 == s1));
1097 CHECK(s1 < s2);
1098 CHECK(!(s2 < s1));
1099 CHECK(s1 <= s2);
1100 CHECK(!(s2 <= s1));
1101 CHECK(s2 > s1);
1102 CHECK(!(s1 > s2));
1103 CHECK(s2 >= s1);
1104 CHECK(!(s1 >= s2));
1105 }
1106 }
1107
1108 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1109 GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
1110 GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
1111 TEST_CASE("basics")
1112 {
1113 auto ptr = as_multi_span(new int[10], 10);
1114 fill(ptr.begin(), ptr.end(), 99);
1115 for (int num : ptr) { CHECK(num == 99); }
1116
1117 delete[] ptr.data();
1118 }
1119
1120 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1121 GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
1122 TEST_CASE("bounds_checks")
1123 {
1124 int arr[10][2];
1125 auto av = as_multi_span(arr);
1126
1127 fill(begin(av), end(av), 0);
1128
1129 av[2][0] = 1;
1130 av[1][1] = 3;
1131
1132 // out of bounds
1133 CHECK_THROWS_AS(av[1][3] = 3, fail_fast);
1134 CHECK_THROWS_AS((av[{1, 3}] = 3), fail_fast);
1135
1136 CHECK_THROWS_AS(av[10][2], fail_fast);
1137 CHECK_THROWS_AS((av[{10, 2}]), fail_fast);
1138
1139 CHECK_THROWS_AS(av[-1][0], fail_fast);
1140 CHECK_THROWS_AS((av[{-1, 0}]), fail_fast);
1141
1142 CHECK_THROWS_AS(av[0][-1], fail_fast);
1143 CHECK_THROWS_AS((av[{0, -1}]), fail_fast);
1144 }
1145
overloaded_func(multi_span<const int,dynamic_range,3,5> exp,int expected_value)1146 void overloaded_func(multi_span<const int, dynamic_range, 3, 5> exp, int expected_value)
1147 {
1148 for (auto val : exp) { CHECK(val == expected_value); }
1149 }
1150
overloaded_func(multi_span<const char,dynamic_range,3,5> exp,char expected_value)1151 void overloaded_func(multi_span<const char, dynamic_range, 3, 5> exp, char expected_value)
1152 {
1153 for (auto val : exp) { CHECK(val == expected_value); }
1154 }
1155
fixed_func(multi_span<int,3,3,5> exp,int expected_value)1156 void fixed_func(multi_span<int, 3, 3, 5> exp, int expected_value)
1157 {
1158 for (auto val : exp) { CHECK(val == expected_value); }
1159 }
1160
1161 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1162 GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
1163 GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
1164 GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
1165 GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
1166 TEST_CASE("span_parameter_test")
1167 {
1168 auto data = new int[4][3][5];
1169
1170 auto av = as_multi_span(data, 4);
1171
1172 CHECK(av.size() == 60);
1173
1174 fill(av.begin(), av.end(), 34);
1175
1176 int count = 0;
__anonbe47408a1e02(int val) 1177 for_each(av.rbegin(), av.rend(), [&](int val) { count += val; });
1178 CHECK(count == 34 * 60);
1179 overloaded_func(av, 34);
1180
1181 overloaded_func(as_multi_span(av, dim(4), dim(3), dim(5)), 34);
1182
1183 // fixed_func(av, 34);
1184 delete[] data;
1185 }
1186
1187 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1188 GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // false positive, checker does not recognize multi_span yet
1189 GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
1190 GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
1191 TEST_CASE("md_access")
1192 {
1193 auto width = 5, height = 20;
1194
1195 auto imgSize = width * height;
1196 auto image_ptr = new int[narrow_cast<std::size_t>(imgSize)][3];
1197
1198 // size check will be done
1199 auto image_view =
1200 as_multi_span(as_multi_span(image_ptr, imgSize), dim(height), dim(width), dim<3>());
1201
1202 iota(image_view.begin(), image_view.end(), 1);
1203
1204 int expected = 0;
1205 for (auto i = 0; i < height; i++)
1206 {
1207 for (auto j = 0; j < width; j++)
1208 {
1209 CHECK(expected + 1 == image_view[i][j][0]);
1210 CHECK(expected + 2 == image_view[i][j][1]);
1211 CHECK(expected + 3 == image_view[i][j][2]);
1212
1213 auto val = image_view[{i, j, 0}];
1214 CHECK(expected + 1 == val);
1215 val = image_view[{i, j, 1}];
1216 CHECK(expected + 2 == val);
1217 val = image_view[{i, j, 2}];
1218 CHECK(expected + 3 == val);
1219
1220 expected += 3;
1221 }
1222 }
1223 }
1224
1225 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1226 GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
1227 GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
1228 GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
1229 GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
1230 TEST_CASE("as_multi_span")
1231 {
1232 {
1233 int* arr = new int[150];
1234
1235 auto av = as_multi_span(arr, dim<10>(), dim(3), dim<5>());
1236
1237 fill(av.begin(), av.end(), 24);
1238 overloaded_func(av, 24);
1239
1240 delete[] arr;
1241
1242 array<int, 15> stdarr{0};
1243 auto av2 = as_multi_span(stdarr);
1244 overloaded_func(as_multi_span(av2, dim(1), dim<3>(), dim<5>()), 0);
1245
1246 string str = "ttttttttttttttt"; // size = 15
1247 auto t = str.data();
1248 GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
1249 (void) t;
1250 auto av3 = as_multi_span(str);
1251 overloaded_func(as_multi_span(av3, dim(1), dim<3>(), dim<5>()), 't');
1252 }
1253
1254 {
1255 string str;
1256 multi_span<char> strspan = as_multi_span(str);
1257 (void) strspan;
1258 const string cstr;
1259 multi_span<const char> cstrspan = as_multi_span(cstr);
1260 (void) cstrspan;
1261 }
1262
1263 {
1264 int a[3][4][5];
1265 auto av = as_multi_span(a);
1266 const int(*b)[4][5];
1267 b = a;
1268 auto bv = as_multi_span(b, 3);
1269
1270 CHECK(av == bv);
1271
1272 const std::array<double, 3> arr = {0.0, 0.0, 0.0};
1273 auto cv = as_multi_span(arr);
1274 (void) cv;
1275
1276 vector<float> vec(3);
1277 auto dv = as_multi_span(vec);
1278 (void) dv;
1279
1280 #ifdef CONFIRM_COMPILATION_ERRORS
1281 auto dv2 = as_multi_span(std::move(vec));
1282 #endif
1283 }
1284 }
1285
1286 GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
1287 TEST_CASE("empty_spans")
1288 {
1289 {
1290 multi_span<int, 0> empty_av(nullptr);
1291
1292 CHECK(empty_av.bounds().index_bounds() == multi_span_index<1>{0});
1293 CHECK_THROWS_AS(empty_av[0], fail_fast);
1294 CHECK_THROWS_AS(empty_av.begin()[0], fail_fast);
1295 CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast);
1296 for (auto& v : empty_av)
1297 {
1298 (void) v;
1299 CHECK(false);
1300 }
1301 }
1302
1303 {
1304 multi_span<int> empty_av = {};
1305 CHECK(empty_av.bounds().index_bounds() == multi_span_index<1>{0});
1306 CHECK_THROWS_AS(empty_av[0], fail_fast);
1307 CHECK_THROWS_AS(empty_av.begin()[0], fail_fast);
1308 CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast);
1309 for (auto& v : empty_av)
1310 {
1311 (void) v;
1312 CHECK(false);
1313 }
1314 }
1315 }
1316
1317 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1318 GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
1319 GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
1320 GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
1321 GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
1322 GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
1323 TEST_CASE("index_constructor")
1324 {
1325 auto arr = new int[8];
1326 for (int i = 0; i < 4; ++i)
1327 {
1328 arr[2 * i] = 4 + i;
1329 arr[2 * i + 1] = i;
1330 }
1331
1332 multi_span<int, dynamic_range> av(arr, 8);
1333
1334 ptrdiff_t a[1] = {0};
1335 multi_span_index<1> i = a;
1336
1337 CHECK(av[i] == 4);
1338
1339 auto av2 = as_multi_span(av, dim<4>(), dim(2));
1340 ptrdiff_t a2[2] = {0, 1};
1341 multi_span_index<2> i2 = a2;
1342
1343 CHECK(av2[i2] == 0);
1344 CHECK(av2[0][i] == 4);
1345
1346 delete[] arr;
1347 }
1348
1349 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1350 TEST_CASE("index_constructors")
1351 {
1352 {
1353 // components of the same type
1354 multi_span_index<3> i1(0, 1, 2);
1355 CHECK(i1[0] == 0);
1356
1357 // components of different types
1358 std::size_t c0 = 0;
1359 std::size_t c1 = 1;
1360 multi_span_index<3> i2(c0, c1, 2);
1361 CHECK(i2[0] == 0);
1362
1363 // from array
1364 multi_span_index<3> i3 = {0, 1, 2};
1365 CHECK(i3[0] == 0);
1366
1367 // from other index of the same size type
1368 multi_span_index<3> i4 = i3;
1369 CHECK(i4[0] == 0);
1370
1371 // default
1372 multi_span_index<3> i7;
1373 CHECK(i7[0] == 0);
1374
1375 // default
1376 multi_span_index<3> i9 = {};
1377 CHECK(i9[0] == 0);
1378 }
1379
1380 {
1381 // components of the same type
1382 multi_span_index<1> i1(0);
1383 CHECK(i1[0] == 0);
1384
1385 // components of different types
1386 std::size_t c0 = 0;
1387 multi_span_index<1> i2(c0);
1388 CHECK(i2[0] == 0);
1389
1390 // from array
1391 multi_span_index<1> i3 = {0};
1392 CHECK(i3[0] == 0);
1393
1394 // from int
1395 multi_span_index<1> i4 = 0;
1396 CHECK(i4[0] == 0);
1397
1398 // from other index of the same size type
1399 multi_span_index<1> i5 = i3;
1400 CHECK(i5[0] == 0);
1401
1402 // default
1403 multi_span_index<1> i8;
1404 CHECK(i8[0] == 0);
1405
1406 // default
1407 multi_span_index<1> i9 = {};
1408 CHECK(i9[0] == 0);
1409 }
1410
1411 #ifdef CONFIRM_COMPILATION_ERRORS
1412 {
1413 multi_span_index<3> i1(0, 1);
1414 multi_span_index<3> i2(0, 1, 2, 3);
1415 multi_span_index<3> i3 = {0};
1416 multi_span_index<3> i4 = {0, 1, 2, 3};
1417 multi_span_index<1> i5 = {0, 1};
1418 }
1419 #endif
1420 }
1421
1422 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1423 TEST_CASE("index_operations")
1424 {
1425 ptrdiff_t a[3] = {0, 1, 2};
1426 ptrdiff_t b[3] = {3, 4, 5};
1427 multi_span_index<3> i = a;
1428 multi_span_index<3> j = b;
1429
1430 CHECK(i[0] == 0);
1431 CHECK(i[1] == 1);
1432 CHECK(i[2] == 2);
1433
1434 {
1435 multi_span_index<3> k = i + j;
1436
1437 CHECK(i[0] == 0);
1438 CHECK(i[1] == 1);
1439 CHECK(i[2] == 2);
1440 CHECK(k[0] == 3);
1441 CHECK(k[1] == 5);
1442 CHECK(k[2] == 7);
1443 }
1444
1445 {
1446 multi_span_index<3> k = i * 3;
1447
1448 CHECK(i[0] == 0);
1449 CHECK(i[1] == 1);
1450 CHECK(i[2] == 2);
1451 CHECK(k[0] == 0);
1452 CHECK(k[1] == 3);
1453 CHECK(k[2] == 6);
1454 }
1455
1456 {
1457 multi_span_index<3> k = 3 * i;
1458
1459 CHECK(i[0] == 0);
1460 CHECK(i[1] == 1);
1461 CHECK(i[2] == 2);
1462 CHECK(k[0] == 0);
1463 CHECK(k[1] == 3);
1464 CHECK(k[2] == 6);
1465 }
1466
1467 {
1468 multi_span_index<2> k = details::shift_left(i);
1469
1470 CHECK(i[0] == 0);
1471 CHECK(i[1] == 1);
1472 CHECK(i[2] == 2);
1473 CHECK(k[0] == 1);
1474 CHECK(k[1] == 2);
1475 }
1476 }
1477
1478 GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
1479 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
iterate_second_column(multi_span<int,dynamic_range,dynamic_range> av)1480 void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
1481 {
1482 auto length = av.size() / 2;
1483
1484 // view to the second column
1485 auto section = av.section({0, 1}, {length, 1});
1486
1487 CHECK(section.size() == length);
1488 for (auto i = 0; i < section.size(); ++i) { CHECK(section[i][0] == av[i][1]); }
1489
1490 for (auto i = 0; i < section.size(); ++i)
1491 {
1492 auto idx = multi_span_index<2>{i, 0}; // avoid braces inside the CHECK macro
1493 CHECK(section[idx] == av[i][1]);
1494 }
1495
1496 CHECK(section.bounds().index_bounds()[0] == length);
1497 CHECK(section.bounds().index_bounds()[1] == 1);
1498 for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i)
1499 {
1500 for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j)
1501 {
1502 auto idx = multi_span_index<2>{i, j}; // avoid braces inside the CHECK macro
1503 CHECK(section[idx] == av[i][1]);
1504 }
1505 }
1506
1507 auto check_sum = 0;
1508 for (auto i = 0; i < length; ++i) { check_sum += av[i][1]; }
1509
1510 {
1511 auto idx = 0;
1512 auto sum = 0;
1513 for (auto num : section)
1514 {
1515 CHECK(num == av[idx][1]);
1516 sum += num;
1517 idx++;
1518 }
1519
1520 CHECK(sum == check_sum);
1521 }
1522 {
1523 auto idx = length - 1;
1524 auto sum = 0;
1525 for (auto iter = section.rbegin(); iter != section.rend(); ++iter)
1526 {
1527 CHECK(*iter == av[idx][1]);
1528 sum += *iter;
1529 idx--;
1530 }
1531
1532 CHECK(sum == check_sum);
1533 }
1534 }
1535
1536 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1537 TEST_CASE("span_section_iteration")
1538 {
1539 int arr[4][2] = {{4, 0}, {5, 1}, {6, 2}, {7, 3}};
1540
1541 // static bounds
1542 {
1543 multi_span<int, 4, 2> av = arr;
1544 iterate_second_column(av);
1545 }
1546 // first bound is dynamic
1547 {
1548 multi_span<int, dynamic_range, 2> av = arr;
1549 iterate_second_column(av);
1550 }
1551 // second bound is dynamic
1552 {
1553 multi_span<int, 4, dynamic_range> av = arr;
1554 iterate_second_column(av);
1555 }
1556 // both bounds are dynamic
1557 {
1558 multi_span<int, dynamic_range, dynamic_range> av = arr;
1559 iterate_second_column(av);
1560 }
1561 }
1562
1563 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1564 GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
1565 GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
1566 GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
1567 GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
1568 TEST_CASE("dynamic_span_section_iteration")
1569 {
1570 auto height = 4, width = 2;
1571 auto size = height * width;
1572
1573 auto arr = new int[narrow_cast<std::size_t>(size)];
1574 for (auto i = 0; i < size; ++i) { arr[i] = i; }
1575
1576 auto av = as_multi_span(arr, size);
1577
1578 // first bound is dynamic
1579 {
1580 multi_span<int, dynamic_range, 2> av2 = as_multi_span(av, dim(height), dim(width));
1581 iterate_second_column(av2);
1582 }
1583 // second bound is dynamic
1584 {
1585 multi_span<int, 4, dynamic_range> av2 = as_multi_span(av, dim(height), dim(width));
1586 iterate_second_column(av2);
1587 }
1588 // both bounds are dynamic
1589 {
1590 multi_span<int, dynamic_range, dynamic_range> av2 =
1591 as_multi_span(av, dim(height), dim(width));
1592 iterate_second_column(av2);
1593 }
1594
1595 delete[] arr;
1596 }
1597
1598 GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
1599 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1600 GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
1601 GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
1602 TEST_CASE("span_structure_size")
1603 {
1604 double(*arr)[3][4] = new double[100][3][4];
1605 multi_span<double, dynamic_range, 3, 4> av1(arr, 10);
1606
1607 struct EffectiveStructure
1608 {
1609 double* v1;
1610 ptrdiff_t v2;
1611 };
1612 CHECK(sizeof(av1) == sizeof(EffectiveStructure));
1613
1614 CHECK_THROWS_AS(av1[10][3][4], fail_fast);
1615
1616 multi_span<const double, dynamic_range, 6, 4> av2 =
1617 as_multi_span(av1, dim(5), dim<6>(), dim<4>());
1618 (void) av2;
1619 }
1620
1621 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1622 TEST_CASE("fixed_size_conversions")
1623 {
1624 int arr[] = {1, 2, 3, 4};
1625
1626 // converting to an multi_span from an equal size array is ok
1627 multi_span<int, 4> av4 = arr;
1628 CHECK(av4.length() == 4);
1629
1630 // converting to dynamic_range a_v is always ok
1631 {
1632 multi_span<int, dynamic_range> av = av4;
1633 (void) av;
1634 }
1635 {
1636 multi_span<int, dynamic_range> av = arr;
1637 (void) av;
1638 }
1639
1640 // initialization or assignment to static multi_span that REDUCES size is NOT ok
1641 #ifdef CONFIRM_COMPILATION_ERRORS
1642 {
1643 multi_span<int, 2> av2 = arr;
1644 }
1645 {
1646 multi_span<int, 2> av2 = av4;
1647 }
1648 #endif
1649
1650 {
1651 multi_span<int, dynamic_range> av = arr;
1652 multi_span<int, 2> av2 = av;
1653 (void) av2;
1654 }
1655
1656 #ifdef CONFIRM_COMPILATION_ERRORS
1657 {
1658 multi_span<int, dynamic_range> av = arr;
1659 multi_span<int, 2, 1> av2 = av.as_multi_span(dim<2>(), dim<2>());
1660 }
1661 #endif
1662
1663 {
1664 multi_span<int, dynamic_range> av = arr;
1665 multi_span<int, 2, 1> av2 = as_multi_span(av, dim(2), dim(2));
__anonbe47408a1f02() 1666 auto workaround_macro = [&]() { return av2[{1, 0}] == 2; };
1667 CHECK(workaround_macro());
1668 }
1669
1670 // but doing so explicitly is ok
1671
1672 // you can convert statically
1673 {
1674 multi_span<int, 2> av2 = {arr, 2};
1675 (void) av2;
1676 }
1677 {
1678 multi_span<int, 1> av2 = av4.first<1>();
1679 (void) av2;
1680 }
1681
1682 // ...or dynamically
1683 {
1684 // NB: implicit conversion to multi_span<int,2> from multi_span<int,dynamic_range>
1685 multi_span<int, 1> av2 = av4.first(1);
1686 (void) av2;
1687 }
1688
1689 // initialization or assignment to static multi_span that requires size INCREASE is not ok.
1690 int arr2[2] = {1, 2};
1691
1692 #ifdef CONFIRM_COMPILATION_ERRORS
1693 {
1694 multi_span<int, 4> av4 = arr2;
1695 }
1696 {
1697 multi_span<int, 2> av2 = arr2;
1698 multi_span<int, 4> av4 = av2;
1699 }
1700 #endif
1701 {
__anonbe47408a2002() 1702 auto f = [&]() {
1703 const multi_span<int, 4> av9 = {arr2, 2};
1704 (void) av9;
1705 };
1706 CHECK_THROWS_AS(f(), fail_fast);
1707 }
1708
1709 // this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one
1710 multi_span<int, dynamic_range> av = arr2;
__anonbe47408a2102() 1711 auto f = [&]() {
1712 const multi_span<int, 4> av2 = av;
1713 (void) av2;
1714 };
1715 CHECK_THROWS_AS(f(), fail_fast);
1716 }
1717
1718 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1719 TEST_CASE("as_writeable_bytes")
1720 {
1721 int a[] = {1, 2, 3, 4};
1722
1723 {
1724 #ifdef CONFIRM_COMPILATION_ERRORS
1725 // you should not be able to get writeable bytes for const objects
1726 multi_span<const int, dynamic_range> av = a;
1727 auto wav = av.as_writeable_bytes();
1728 #endif
1729 }
1730
1731 {
1732 multi_span<int, dynamic_range> av;
1733 auto wav = as_writeable_bytes(av);
1734 CHECK(wav.length() == av.length());
1735 CHECK(wav.length() == 0);
1736 CHECK(wav.size_bytes() == 0);
1737 }
1738
1739 {
1740 multi_span<int, dynamic_range> av = a;
1741 auto wav = as_writeable_bytes(av);
1742 CHECK(wav.data() == reinterpret_cast<byte*>(&a[0]));
1743 CHECK(static_cast<std::size_t>(wav.length()) == sizeof(a));
1744 }
1745 }
1746
1747
1748 GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
1749 GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
1750 GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
1751 TEST_CASE("iterator")
1752 {
1753 int a[] = {1, 2, 3, 4};
1754
1755 {
1756 multi_span<int, dynamic_range> av = a;
1757 auto wav = as_writeable_bytes(av);
1758 for (auto& b : wav) {
1759 #if defined(__cplusplus) && (__cplusplus >= 201703L)
1760 b = byte{0};
1761 #else
1762 GSL_SUPPRESS(es.49)
1763 b = byte(0);
1764 #endif
1765 }
1766
1767 for (std::size_t i = 0; i < 4; ++i) {
1768 CHECK(a[i] == 0);
1769 }
1770 }
1771
1772 {
1773 multi_span<int, dynamic_range> av = a;
1774 for (auto& n : av) {
1775 n = 1;
1776 }
1777 for (std::size_t i = 0; i < 4; ++i) {
1778 CHECK(a[i] == 1);
1779 }
1780 }
1781 }
1782
1783 #ifdef CONFIRM_COMPILATION_ERRORS
1784 copy(src_span_static, dst_span_static);
1785 #endif
1786