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