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 #include <UnitTest++/UnitTest++.h>
18 #include <gsl/span>
19
20 #include <iostream>
21 #include <list>
22 #include <map>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 #include <regex>
27
28 using namespace std;
29 using namespace gsl;
30
31 namespace
32 {
33 struct BaseClass
34 {
35 };
36 struct DerivedClass : BaseClass
37 {
38 };
39 }
40
SUITE(span_tests)41 SUITE(span_tests)
42 {
43 TEST(default_constructor)
44 {
45 {
46 span<int> s;
47 CHECK(s.length() == 0 && s.data() == nullptr);
48
49 span<const int> cs;
50 CHECK(cs.length() == 0 && cs.data() == nullptr);
51 }
52
53 {
54 span<int, 0> s;
55 CHECK(s.length() == 0 && s.data() == nullptr);
56
57 span<const int, 0> cs;
58 CHECK(cs.length() == 0 && cs.data() == nullptr);
59 }
60
61 {
62 #ifdef CONFIRM_COMPILATION_ERRORS
63 span<int, 1> s;
64 CHECK(s.length() == 1 && s.data() == nullptr); // explains why it can't compile
65 #endif
66 }
67
68 {
69 span<int> s{};
70 CHECK(s.length() == 0 && s.data() == nullptr);
71
72 span<const int> cs{};
73 CHECK(cs.length() == 0 && cs.data() == nullptr);
74 }
75 }
76
77 TEST(size_optimization)
78 {
79 {
80 span<int> s;
81 CHECK(sizeof(s) == sizeof(int*) + sizeof(ptrdiff_t));
82 }
83
84 {
85 span<int, 0> s;
86 CHECK(sizeof(s) == sizeof(int*));
87 }
88 }
89
90 TEST(from_nullptr_constructor)
91 {
92 {
93 span<int> s = nullptr;
94 CHECK(s.length() == 0 && s.data() == nullptr);
95
96 span<const int> cs = nullptr;
97 CHECK(cs.length() == 0 && cs.data() == nullptr);
98 }
99
100 {
101 span<int, 0> s = nullptr;
102 CHECK(s.length() == 0 && s.data() == nullptr);
103
104 span<const int, 0> cs = nullptr;
105 CHECK(cs.length() == 0 && cs.data() == nullptr);
106 }
107
108 {
109 #ifdef CONFIRM_COMPILATION_ERRORS
110 span<int, 1> s = nullptr;
111 CHECK(s.length() == 1 && s.data() == nullptr); // explains why it can't compile
112 #endif
113 }
114
115 {
116 span<int> s{nullptr};
117 CHECK(s.length() == 0 && s.data() == nullptr);
118
119 span<const int> cs{nullptr};
120 CHECK(cs.length() == 0 && cs.data() == nullptr);
121 }
122
123 {
124 span<int*> s{nullptr};
125 CHECK(s.length() == 0 && s.data() == nullptr);
126
127 span<const int*> cs{nullptr};
128 CHECK(cs.length() == 0 && cs.data() == nullptr);
129 }
130 }
131
132 TEST(from_nullptr_length_constructor)
133 {
134 {
135 span<int> s{nullptr, static_cast<span<int>::index_type>(0)};
136 CHECK(s.length() == 0 && s.data() == nullptr);
137
138 span<const int> cs{nullptr, static_cast<span<int>::index_type>(0)};
139 CHECK(cs.length() == 0 && cs.data() == nullptr);
140 }
141
142 {
143 span<int, 0> s{nullptr, static_cast<span<int>::index_type>(0)};
144 CHECK(s.length() == 0 && s.data() == nullptr);
145
146 span<const int, 0> cs{nullptr, static_cast<span<int>::index_type>(0)};
147 CHECK(cs.length() == 0 && cs.data() == nullptr);
148 }
149
150 {
151 auto workaround_macro = []() { span<int, 1> s{ nullptr, static_cast<span<int>::index_type>(0) }; };
152 CHECK_THROW(workaround_macro(), fail_fast);
153 }
154
155 {
156 auto workaround_macro = []() { span<int> s{nullptr, 1}; };
157 CHECK_THROW(workaround_macro(), fail_fast);
158
159 auto const_workaround_macro = []() { span<const int> cs{nullptr, 1}; };
160 CHECK_THROW(const_workaround_macro(), fail_fast);
161 }
162
163 {
164 auto workaround_macro = []() { span<int, 0> s{nullptr, 1}; };
165 CHECK_THROW(workaround_macro(), fail_fast);
166
167 auto const_workaround_macro = []() { span<const int, 0> s{nullptr, 1}; };
168 CHECK_THROW(const_workaround_macro(), fail_fast);
169 }
170
171 {
172 span<int*> s{nullptr, static_cast<span<int>::index_type>(0)};
173 CHECK(s.length() == 0 && s.data() == nullptr);
174
175 span<const int*> cs{nullptr, static_cast<span<int>::index_type>(0)};
176 CHECK(cs.length() == 0 && cs.data() == nullptr);
177 }
178 }
179
180 TEST(from_pointer_length_constructor)
181 {
182 int arr[4] = {1, 2, 3, 4};
183
184 {
185 span<int> s{&arr[0], 2};
186 CHECK(s.length() == 2 && s.data() == &arr[0]);
187 CHECK(s[0] == 1 && s[1] == 2);
188 }
189
190 {
191 span<int, 2> s{&arr[0], 2};
192 CHECK(s.length() == 2 && s.data() == &arr[0]);
193 CHECK(s[0] == 1 && s[1] == 2);
194 }
195
196 {
197 int* p = nullptr;
198 span<int> s{p, static_cast<span<int>::index_type>(0)};
199 CHECK(s.length() == 0 && s.data() == nullptr);
200 }
201
202 {
203 int* p = nullptr;
204 auto workaround_macro = [=]() { span<int> s{p, 2}; };
205 CHECK_THROW(workaround_macro(), fail_fast);
206 }
207 }
208
209 TEST(from_pointer_pointer_constructor)
210 {
211 int arr[4] = {1, 2, 3, 4};
212
213 {
214 span<int> s{&arr[0], &arr[2]};
215 CHECK(s.length() == 2 && s.data() == &arr[0]);
216 CHECK(s[0] == 1 && s[1] == 2);
217 }
218
219 {
220 span<int, 2> s{&arr[0], &arr[2]};
221 CHECK(s.length() == 2 && s.data() == &arr[0]);
222 CHECK(s[0] == 1 && s[1] == 2);
223 }
224
225 {
226 span<int> s{&arr[0], &arr[0]};
227 CHECK(s.length() == 0 && s.data() == &arr[0]);
228 }
229
230 {
231 span<int, 0> s{&arr[0], &arr[0]};
232 CHECK(s.length() == 0 && s.data() == &arr[0]);
233 }
234
235 // this will fail the std::distance() precondition, which asserts on MSVC debug builds
236 //{
237 // auto workaround_macro = [&]() { span<int> s{&arr[1], &arr[0]}; };
238 // CHECK_THROW(workaround_macro(), fail_fast);
239 //}
240
241 // this will fail the std::distance() precondition, which asserts on MSVC debug builds
242 //{
243 // int* p = nullptr;
244 // auto workaround_macro = [&]() { span<int> s{&arr[0], p}; };
245 // CHECK_THROW(workaround_macro(), fail_fast);
246 //}
247
248 {
249 int* p = nullptr;
250 span<int> s{ p, p };
251 CHECK(s.length() == 0 && s.data() == nullptr);
252 }
253
254 {
255 int* p = nullptr;
256 span<int, 0> s{ p, p };
257 CHECK(s.length() == 0 && s.data() == nullptr);
258 }
259
260 // this will fail the std::distance() precondition, which asserts on MSVC debug builds
261 //{
262 // int* p = nullptr;
263 // auto workaround_macro = [&]() { span<int> s{&arr[0], p}; };
264 // CHECK_THROW(workaround_macro(), fail_fast);
265 //}
266 }
267
268 TEST(from_array_constructor)
269 {
270 int arr[5] = {1, 2, 3, 4, 5};
271
272 {
273 span<int> s{arr};
274 CHECK(s.length() == 5 && s.data() == &arr[0]);
275 }
276
277 {
278 span<int, 5> s{arr};
279 CHECK(s.length() == 5 && s.data() == &arr[0]);
280 }
281
282 int arr2d[2][3] = { 1, 2, 3, 4, 5, 6 };
283
284 #ifdef CONFIRM_COMPILATION_ERRORS
285 {
286 span<int, 6> s{arr};
287 }
288
289 {
290 span<int, 0> s{arr};
291 CHECK(s.length() == 0 && s.data() == &arr[0]);
292 }
293
294 {
295 span<int> s{arr2d};
296 CHECK(s.length() == 6 && s.data() == &arr2d[0][0]);
297 CHECK(s[0] == 1 && s[5] == 6);
298 }
299
300 {
301 span<int, 0> s{arr2d};
302 CHECK(s.length() == 0 && s.data() == &arr2d[0][0]);
303 }
304
305 {
306 span<int, 6> s{ arr2d };
307 }
308 #endif
309 {
310 span<int[3]> s{ &(arr2d[0]), 1 };
311 CHECK(s.length() == 1 && s.data() == &arr2d[0]);
312 }
313
314 int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
315
316 #ifdef CONFIRM_COMPILATION_ERRORS
317 {
318 span<int> s{arr3d};
319 CHECK(s.length() == 12 && s.data() == &arr3d[0][0][0]);
320 CHECK(s[0] == 1 && s[11] == 12);
321 }
322
323 {
324 span<int, 0> s{arr3d};
325 CHECK(s.length() == 0 && s.data() == &arr3d[0][0][0]);
326 }
327
328 {
329 span<int, 11> s{arr3d};
330 }
331
332 {
333 span<int, 12> s{arr3d};
334 CHECK(s.length() == 12 && s.data() == &arr3d[0][0][0]);
335 CHECK(s[0] == 1 && s[5] == 6);
336 }
337 #endif
338 {
339 span<int[3][2]> s{&arr3d[0], 1};
340 CHECK(s.length() == 1 && s.data() == &arr3d[0]);
341 }
342 }
343
344 TEST(from_dynamic_array_constructor)
345 {
346 double(*arr)[3][4] = new double[100][3][4];
347
348 {
349 span<double> s(&arr[0][0][0], 10);
350 CHECK(s.length() == 10 && s.data() == &arr[0][0][0]);
351 }
352
353 delete[] arr;
354 }
355
356 TEST(from_std_array_constructor)
357 {
358 std::array<int, 4> arr = {1, 2, 3, 4};
359
360 {
361 span<int> s{arr};
362 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data());
363
364 span<const int> cs{arr};
365 CHECK(cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data());
366 }
367
368 {
369 span<int, 4> s{arr};
370 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data());
371
372 span<const int, 4> cs{arr};
373 CHECK(cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data());
374 }
375
376 #ifdef CONFIRM_COMPILATION_ERRORS
377 {
378 span<int, 2> s{arr};
379 CHECK(s.size() == 2 && s.data() == arr.data());
380
381 span<const int, 2> cs{arr};
382 CHECK(cs.size() == 2 && cs.data() == arr.data());
383 }
384
385 {
386 span<int, 0> s{arr};
387 CHECK(s.size() == 0 && s.data() == arr.data());
388
389 span<const int, 0> cs{arr};
390 CHECK(cs.size() == 0 && cs.data() == arr.data());
391 }
392
393 {
394 span<int, 5> s{arr};
395 }
396
397 {
398 auto get_an_array = []()->std::array<int, 4> { return{1, 2, 3, 4}; };
399 auto take_a_span = [](span<int> s) { static_cast<void>(s); };
400 // try to take a temporary std::array
401 take_a_span(get_an_array());
402 }
403 #endif
404
405 {
406 auto get_an_array = []() -> std::array<int, 4> { return { 1, 2, 3, 4 }; };
407 auto take_a_span = [](span<const int> s) { static_cast<void>(s); };
408 // try to take a temporary std::array
409 take_a_span(get_an_array());
410 }
411 }
412
413 TEST(from_const_std_array_constructor)
414 {
415 const std::array<int, 4> arr = {1, 2, 3, 4};
416
417 {
418 span<const int> s{arr};
419 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data());
420 }
421
422 {
423 span<const int, 4> s{arr};
424 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data());
425 }
426
427 #ifdef CONFIRM_COMPILATION_ERRORS
428 {
429 span<const int, 2> s{arr};
430 CHECK(s.size() == 2 && s.data() == arr.data());
431 }
432
433 {
434 span<const int, 0> s{arr};
435 CHECK(s.size() == 0 && s.data() == arr.data());
436 }
437
438 {
439 span<const int, 5> s{arr};
440 }
441 #endif
442
443 {
444 auto get_an_array = []() -> const std::array<int, 4> { return {1, 2, 3, 4}; };
445 auto take_a_span = [](span<const int> s) { static_cast<void>(s); };
446 // try to take a temporary std::array
447 take_a_span(get_an_array());
448 }
449 }
450
451 TEST(from_std_array_const_constructor)
452 {
453 std::array<const int, 4> arr = {1, 2, 3, 4};
454
455 {
456 span<const int> s{arr};
457 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data());
458 }
459
460 {
461 span<const int, 4> s{arr};
462 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data());
463 }
464
465 #ifdef CONFIRM_COMPILATION_ERRORS
466 {
467 span<const int, 2> s{arr};
468 CHECK(s.size() == 2 && s.data() == arr.data());
469 }
470
471 {
472 span<const int, 0> s{arr};
473 CHECK(s.size() == 0 && s.data() == arr.data());
474 }
475
476 {
477 span<const int, 5> s{arr};
478 }
479
480 {
481 span<int, 4> s{arr};
482 }
483 #endif
484 }
485
486 TEST(from_container_constructor)
487 {
488 std::vector<int> v = {1, 2, 3};
489 const std::vector<int> cv = v;
490
491 {
492 span<int> s{v};
493 CHECK(s.size() == narrow_cast<std::ptrdiff_t>(v.size()) && s.data() == v.data());
494
495 span<const int> cs{v};
496 CHECK(cs.size() == narrow_cast<std::ptrdiff_t>(v.size()) && cs.data() == v.data());
497 }
498
499 std::string str = "hello";
500 const std::string cstr = "hello";
501
502 {
503 #ifdef CONFIRM_COMPILATION_ERRORS
504 span<char> s{str};
505 CHECK(s.size() == narrow_cast<std::ptrdiff_t>(str.size()) && s.data() == str.data());
506 #endif
507 span<const char> cs{str};
508 CHECK(cs.size() == narrow_cast<std::ptrdiff_t>(str.size()) && cs.data() == str.data());
509 }
510
511 {
512 #ifdef CONFIRM_COMPILATION_ERRORS
513 span<char> s{cstr};
514 #endif
515 span<const char> cs{cstr};
516 CHECK(cs.size() == narrow_cast<std::ptrdiff_t>(cstr.size()) &&
517 cs.data() == cstr.data());
518 }
519
520 {
521 #ifdef CONFIRM_COMPILATION_ERRORS
522 auto get_temp_vector = []() -> std::vector<int> { return {}; };
523 auto use_span = [](span<int> s) { static_cast<void>(s); };
524 use_span(get_temp_vector());
525 #endif
526 }
527
528 {
529 auto get_temp_vector = []() -> std::vector<int> { return{}; };
530 auto use_span = [](span<const int> s) { static_cast<void>(s); };
531 use_span(get_temp_vector());
532 }
533
534 {
535 #ifdef CONFIRM_COMPILATION_ERRORS
536 auto get_temp_string = []() -> std::string { return{}; };
537 auto use_span = [](span<char> s) { static_cast<void>(s); };
538 use_span(get_temp_string());
539 #endif
540 }
541
542 {
543 auto get_temp_string = []() -> std::string { return {}; };
544 auto use_span = [](span<const char> s) { static_cast<void>(s); };
545 use_span(get_temp_string());
546 }
547
548 {
549 #ifdef CONFIRM_COMPILATION_ERRORS
550 auto get_temp_vector = []() -> const std::vector<int> { return {}; };
551 auto use_span = [](span<const char> s) { static_cast<void>(s); };
552 use_span(get_temp_vector());
553 #endif
554 }
555
556 {
557 auto get_temp_string = []() -> const std::string { return {}; };
558 auto use_span = [](span<const char> s) { static_cast<void>(s); };
559 use_span(get_temp_string());
560 }
561
562 {
563 #ifdef CONFIRM_COMPILATION_ERRORS
564 std::map<int, int> m;
565 span<int> s{m};
566 #endif
567 }
568 }
569
570 TEST(from_convertible_span_constructor)
571 {
572 {
573 span<DerivedClass> avd;
574 span<const DerivedClass> avcd = avd;
575 static_cast<void>(avcd);
576 }
577
578 {
579 #ifdef CONFIRM_COMPILATION_ERRORS
580 span<DerivedClass> avd;
581 span<BaseClass> avb = avd;
582 static_cast<void>(avb);
583 #endif
584 }
585
586 #ifdef CONFIRM_COMPILATION_ERRORS
587 {
588 span<int> s;
589 span<unsigned int> s2 = s;
590 static_cast<void>(s2);
591 }
592
593 {
594 span<int> s;
595 span<const unsigned int> s2 = s;
596 static_cast<void>(s2);
597 }
598
599 {
600 span<int> s;
601 span<short> s2 = s;
602 static_cast<void>(s2);
603 }
604 #endif
605 }
606
607 TEST(copy_move_and_assignment)
608 {
609 span<int> s1;
610 CHECK(s1.empty());
611
612 int arr[] = {3, 4, 5};
613
614 span<const int> s2 = arr;
615 CHECK(s2.length() == 3 && s2.data() == &arr[0]);
616
617 s2 = s1;
618 CHECK(s2.empty());
619
620 auto get_temp_span = [&]() -> span<int> { return {&arr[1], 2}; };
621 auto use_span = [&](span<const int> s) { CHECK(s.length() == 2 && s.data() == &arr[1]); };
622 use_span(get_temp_span());
623
624 s1 = get_temp_span();
625 CHECK(s1.length() == 2 && s1.data() == &arr[1]);
626 }
627
628 TEST(first)
629 {
630 int arr[5] = {1, 2, 3, 4, 5};
631
632 {
633 span<int, 5> av = arr;
634 CHECK(av.first<2>().length() == 2);
635 CHECK(av.first(2).length() == 2);
636 }
637
638 {
639 span<int, 5> av = arr;
640 CHECK(av.first<0>().length() == 0);
641 CHECK(av.first(0).length() == 0);
642 }
643
644 {
645 span<int, 5> av = arr;
646 CHECK(av.first<5>().length() == 5);
647 CHECK(av.first(5).length() == 5);
648 }
649
650 {
651 span<int, 5> av = arr;
652 #ifdef CONFIRM_COMPILATION_ERRORS
653 CHECK(av.first<6>().length() == 6);
654 CHECK(av.first<-1>().length() == -1);
655 #endif
656 CHECK_THROW(av.first(6).length(), fail_fast);
657 }
658
659 {
660 span<int> av;
661 CHECK(av.first<0>().length() == 0);
662 CHECK(av.first(0).length() == 0);
663 }
664 }
665
666 TEST(last)
667 {
668 int arr[5] = {1, 2, 3, 4, 5};
669
670 {
671 span<int, 5> av = arr;
672 CHECK(av.last<2>().length() == 2);
673 CHECK(av.last(2).length() == 2);
674 }
675
676 {
677 span<int, 5> av = arr;
678 CHECK(av.last<0>().length() == 0);
679 CHECK(av.last(0).length() == 0);
680 }
681
682 {
683 span<int, 5> av = arr;
684 CHECK(av.last<5>().length() == 5);
685 CHECK(av.last(5).length() == 5);
686 }
687
688 {
689 span<int, 5> av = arr;
690 #ifdef CONFIRM_COMPILATION_ERRORS
691 CHECK(av.last<6>().length() == 6);
692 #endif
693 CHECK_THROW(av.last(6).length(), fail_fast);
694 }
695
696 {
697 span<int> av;
698 CHECK(av.last<0>().length() == 0);
699 CHECK(av.last(0).length() == 0);
700 }
701 }
702
703 TEST(subspan)
704 {
705 int arr[5] = {1, 2, 3, 4, 5};
706
707 {
708 span<int, 5> av = arr;
709 CHECK((av.subspan<2, 2>().length() == 2));
710 CHECK(av.subspan(2, 2).length() == 2);
711 CHECK(av.subspan(2, 3).length() == 3);
712 }
713
714 {
715 span<int, 5> av = arr;
716 CHECK((av.subspan<0, 0>().length() == 0));
717 CHECK(av.subspan(0, 0).length() == 0);
718 }
719
720 {
721 span<int, 5> av = arr;
722 CHECK((av.subspan<0, 5>().length() == 5));
723 CHECK(av.subspan(0, 5).length() == 5);
724 CHECK_THROW(av.subspan(0, 6).length(), fail_fast);
725 CHECK_THROW(av.subspan(1, 5).length(), fail_fast);
726 }
727
728 {
729 span<int, 5> av = arr;
730 CHECK((av.subspan<4, 0>().length() == 0));
731 CHECK(av.subspan(4, 0).length() == 0);
732 CHECK(av.subspan(5, 0).length() == 0);
733 CHECK_THROW(av.subspan(6, 0).length(), fail_fast);
734 }
735
736 {
737 span<int> av;
738 CHECK((av.subspan<0, 0>().length() == 0));
739 CHECK(av.subspan(0, 0).length() == 0);
740 CHECK_THROW((av.subspan<1, 0>().length()), fail_fast);
741 }
742
743 {
744 span<int> av;
745 CHECK(av.subspan(0).length() == 0);
746 CHECK_THROW(av.subspan(1).length(), fail_fast);
747 }
748
749 {
750 span<int> av = arr;
751 CHECK(av.subspan(0).length() == 5);
752 CHECK(av.subspan(1).length() == 4);
753 CHECK(av.subspan(4).length() == 1);
754 CHECK(av.subspan(5).length() == 0);
755 CHECK_THROW(av.subspan(6).length(), fail_fast);
756 auto av2 = av.subspan(1);
757 for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2);
758 }
759
760 {
761 span<int, 5> av = arr;
762 CHECK(av.subspan(0).length() == 5);
763 CHECK(av.subspan(1).length() == 4);
764 CHECK(av.subspan(4).length() == 1);
765 CHECK(av.subspan(5).length() == 0);
766 CHECK_THROW(av.subspan(6).length(), fail_fast);
767 auto av2 = av.subspan(1);
768 for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2);
769 }
770 }
771
772 TEST(at_call)
773 {
774 int arr[4] = {1, 2, 3, 4};
775
776 {
777 span<int> s = arr;
778 CHECK(s.at(0) == 1);
779 CHECK_THROW(s.at(5), fail_fast);
780 }
781
782 {
783 int arr2d[2] = {1, 6};
784 span<int, 2> s = arr2d;
785 CHECK(s.at(0) == 1);
786 CHECK(s.at(1) == 6);
787 CHECK_THROW(s.at(2) ,fail_fast);
788 }
789 }
790
791 TEST(operator_function_call)
792 {
793 int arr[4] = {1, 2, 3, 4};
794
795 {
796 span<int> s = arr;
797 CHECK(s(0) == 1);
798 CHECK_THROW(s(5), fail_fast);
799 }
800
801 {
802 int arr2d[2] = {1, 6};
803 span<int, 2> s = arr2d;
804 CHECK(s(0) == 1);
805 CHECK(s(1) == 6);
806 CHECK_THROW(s(2) ,fail_fast);
807 }
808 }
809
810 TEST(iterator_default_init)
811 {
812 span<int>::iterator it1;
813 span<int>::iterator it2;
814 CHECK(it1 == it2);
815 }
816
817 TEST(const_iterator_default_init)
818 {
819 span<int>::const_iterator it1;
820 span<int>::const_iterator it2;
821 CHECK(it1 == it2);
822 }
823
824 TEST(iterator_conversions)
825 {
826 span<int>::iterator badIt;
827 span<int>::const_iterator badConstIt;
828 CHECK(badIt == badConstIt);
829
830 int a[] = { 1, 2, 3, 4 };
831 span<int> s = a;
832
833 auto it = s.begin();
834 auto cit = s.cbegin();
835
836 CHECK(it == cit);
837 CHECK(cit == it);
838
839 span<int>::const_iterator cit2 = it;
840 CHECK(cit2 == cit);
841
842 span<int>::const_iterator cit3 = it + 4;
843 CHECK(cit3 == s.cend());
844 }
845
846 TEST(iterator_comparisons)
847 {
848 int a[] = { 1, 2, 3, 4 };
849 {
850 span<int> s = a;
851 span<int>::iterator it = s.begin();
852 auto it2 = it + 1;
853 span<int>::const_iterator cit = s.cbegin();
854
855 CHECK(it == cit);
856 CHECK(cit == it);
857 CHECK(it == it);
858 CHECK(cit == cit);
859 CHECK(cit == s.begin());
860 CHECK(s.begin() == cit);
861 CHECK(s.cbegin() == cit);
862 CHECK(it == s.begin());
863 CHECK(s.begin() == it);
864
865 CHECK(it != it2);
866 CHECK(it2 != it);
867 CHECK(it != s.end());
868 CHECK(it2 != s.end());
869 CHECK(s.end() != it);
870 CHECK(it2 != cit);
871 CHECK(cit != it2);
872
873 CHECK(it < it2);
874 CHECK(it <= it2);
875 CHECK(it2 <= s.end());
876 CHECK(it < s.end());
877 CHECK(it <= cit);
878 CHECK(cit <= it);
879 CHECK(cit < it2);
880 CHECK(cit <= it2);
881 CHECK(cit < s.end());
882 CHECK(cit <= s.end());
883
884 CHECK(it2 > it);
885 CHECK(it2 >= it);
886 CHECK(s.end() > it2);
887 CHECK(s.end() >= it2);
888 CHECK(it2 > cit);
889 CHECK(it2 >= cit);
890 }
891 }
892
893 TEST(begin_end)
894 {
895 {
896 int a[] = { 1, 2, 3, 4 };
897 span<int> s = a;
898
899 span<int>::iterator it = s.begin();
900 span<int>::iterator it2 = std::begin(s);
901 CHECK(it == it2);
902
903 it = s.end();
904 it2 = std::end(s);
905 CHECK(it == it2);
906 }
907
908 {
909 int a[] = { 1, 2, 3, 4 };
910 span<int> s = a;
911
912 auto it = s.begin();
913 auto first = it;
914 CHECK(it == first);
915 CHECK(*it == 1);
916
917 auto beyond = s.end();
918 CHECK(it != beyond);
919 CHECK_THROW(*beyond, fail_fast);
920
921 CHECK(beyond - first == 4);
922 CHECK(first - first == 0);
923 CHECK(beyond - beyond == 0);
924
925 ++it;
926 CHECK(it - first == 1);
927 CHECK(*it == 2);
928 *it = 22;
929 CHECK(*it == 22);
930 CHECK(beyond - it == 3);
931
932 it = first;
933 CHECK(it == first);
934 while (it != s.end())
935 {
936 *it = 5;
937 ++it;
938 }
939
940 CHECK(it == beyond);
941 CHECK(it - beyond == 0);
942
943 for (auto& n : s)
944 {
945 CHECK(n == 5);
946 }
947 }
948 }
949
950 TEST(cbegin_cend)
951 {
952 {
953 int a[] = { 1, 2, 3, 4 };
954 span<int> s = a;
955
956 span<int>::const_iterator cit = s.cbegin();
957 span<int>::const_iterator cit2 = std::cbegin(s);
958 CHECK(cit == cit2);
959
960 cit = s.cend();
961 cit2 = std::cend(s);
962 CHECK(cit == cit2);
963 }
964
965 {
966 int a[] = {1, 2, 3, 4};
967 span<int> s = a;
968
969 auto it = s.cbegin();
970 auto first = it;
971 CHECK(it == first);
972 CHECK(*it == 1);
973
974 auto beyond = s.cend();
975 CHECK(it != beyond);
976 CHECK_THROW(*beyond, fail_fast);
977
978 CHECK(beyond - first == 4);
979 CHECK(first - first == 0);
980 CHECK(beyond - beyond == 0);
981
982 ++it;
983 CHECK(it - first == 1);
984 CHECK(*it == 2);
985 CHECK(beyond - it == 3);
986
987 int last = 0;
988 it = first;
989 CHECK(it == first);
990 while (it != s.cend())
991 {
992 CHECK(*it == last + 1);
993
994 last = *it;
995 ++it;
996 }
997
998 CHECK(it == beyond);
999 CHECK(it - beyond == 0);
1000 }
1001 }
1002
1003 TEST(rbegin_rend)
1004 {
1005 {
1006 int a[] = {1, 2, 3, 4};
1007 span<int> s = a;
1008
1009 auto it = s.rbegin();
1010 auto first = it;
1011 CHECK(it == first);
1012 CHECK(*it == 4);
1013
1014 auto beyond = s.rend();
1015 CHECK(it != beyond);
1016 CHECK_THROW(*beyond, fail_fast);
1017
1018 CHECK(beyond - first == 4);
1019 CHECK(first - first == 0);
1020 CHECK(beyond - beyond == 0);
1021
1022 ++it;
1023 CHECK(it - first == 1);
1024 CHECK(*it == 3);
1025 *it = 22;
1026 CHECK(*it == 22);
1027 CHECK(beyond - it == 3);
1028
1029 it = first;
1030 CHECK(it == first);
1031 while (it != s.rend())
1032 {
1033 *it = 5;
1034 ++it;
1035 }
1036
1037 CHECK(it == beyond);
1038 CHECK(it - beyond == 0);
1039
1040 for (auto& n : s)
1041 {
1042 CHECK(n == 5);
1043 }
1044 }
1045 }
1046
1047 TEST(crbegin_crend)
1048 {
1049 {
1050 int a[] = {1, 2, 3, 4};
1051 span<int> s = a;
1052
1053 auto it = s.crbegin();
1054 auto first = it;
1055 CHECK(it == first);
1056 CHECK(*it == 4);
1057
1058 auto beyond = s.crend();
1059 CHECK(it != beyond);
1060 CHECK_THROW(*beyond, fail_fast);
1061
1062 CHECK(beyond - first == 4);
1063 CHECK(first - first == 0);
1064 CHECK(beyond - beyond == 0);
1065
1066 ++it;
1067 CHECK(it - first == 1);
1068 CHECK(*it == 3);
1069 CHECK(beyond - it == 3);
1070
1071 it = first;
1072 CHECK(it == first);
1073 int last = 5;
1074 while (it != s.crend())
1075 {
1076 CHECK(*it == last - 1);
1077 last = *it;
1078
1079 ++it;
1080 }
1081
1082 CHECK(it == beyond);
1083 CHECK(it - beyond == 0);
1084 }
1085 }
1086
1087 TEST(comparison_operators)
1088 {
1089 {
1090 span<int> s1 = nullptr;
1091 span<int> s2 = nullptr;
1092 CHECK(s1 == s2);
1093 CHECK(!(s1 != s2));
1094 CHECK(!(s1 < s2));
1095 CHECK(s1 <= s2);
1096 CHECK(!(s1 > s2));
1097 CHECK(s1 >= s2);
1098 CHECK(s2 == s1);
1099 CHECK(!(s2 != s1));
1100 CHECK(!(s2 < s1));
1101 CHECK(s2 <= s1);
1102 CHECK(!(s2 > s1));
1103 CHECK(s2 >= s1);
1104 }
1105
1106 {
1107 int arr[] = {2, 1};
1108 span<int> s1 = arr;
1109 span<int> s2 = arr;
1110
1111 CHECK(s1 == s2);
1112 CHECK(!(s1 != s2));
1113 CHECK(!(s1 < s2));
1114 CHECK(s1 <= s2);
1115 CHECK(!(s1 > s2));
1116 CHECK(s1 >= s2);
1117 CHECK(s2 == s1);
1118 CHECK(!(s2 != s1));
1119 CHECK(!(s2 < s1));
1120 CHECK(s2 <= s1);
1121 CHECK(!(s2 > s1));
1122 CHECK(s2 >= s1);
1123 }
1124
1125 {
1126 int arr[] = {2, 1}; // bigger
1127
1128 span<int> s1 = nullptr;
1129 span<int> s2 = arr;
1130
1131 CHECK(s1 != s2);
1132 CHECK(s2 != s1);
1133 CHECK(!(s1 == s2));
1134 CHECK(!(s2 == s1));
1135 CHECK(s1 < s2);
1136 CHECK(!(s2 < s1));
1137 CHECK(s1 <= s2);
1138 CHECK(!(s2 <= s1));
1139 CHECK(s2 > s1);
1140 CHECK(!(s1 > s2));
1141 CHECK(s2 >= s1);
1142 CHECK(!(s1 >= s2));
1143 }
1144
1145 {
1146 int arr1[] = {1, 2};
1147 int arr2[] = {1, 2};
1148 span<int> s1 = arr1;
1149 span<int> s2 = arr2;
1150
1151 CHECK(s1 == s2);
1152 CHECK(!(s1 != s2));
1153 CHECK(!(s1 < s2));
1154 CHECK(s1 <= s2);
1155 CHECK(!(s1 > s2));
1156 CHECK(s1 >= s2);
1157 CHECK(s2 == s1);
1158 CHECK(!(s2 != s1));
1159 CHECK(!(s2 < s1));
1160 CHECK(s2 <= s1);
1161 CHECK(!(s2 > s1));
1162 CHECK(s2 >= s1);
1163 }
1164
1165 {
1166 int arr[] = {1, 2, 3};
1167
1168 span<int> s1 = {&arr[0], 2}; // shorter
1169 span<int> s2 = arr; // longer
1170
1171 CHECK(s1 != s2);
1172 CHECK(s2 != s1);
1173 CHECK(!(s1 == s2));
1174 CHECK(!(s2 == s1));
1175 CHECK(s1 < s2);
1176 CHECK(!(s2 < s1));
1177 CHECK(s1 <= s2);
1178 CHECK(!(s2 <= s1));
1179 CHECK(s2 > s1);
1180 CHECK(!(s1 > s2));
1181 CHECK(s2 >= s1);
1182 CHECK(!(s1 >= s2));
1183 }
1184
1185 {
1186 int arr1[] = {1, 2}; // smaller
1187 int arr2[] = {2, 1}; // bigger
1188
1189 span<int> s1 = arr1;
1190 span<int> s2 = arr2;
1191
1192 CHECK(s1 != s2);
1193 CHECK(s2 != s1);
1194 CHECK(!(s1 == s2));
1195 CHECK(!(s2 == s1));
1196 CHECK(s1 < s2);
1197 CHECK(!(s2 < s1));
1198 CHECK(s1 <= s2);
1199 CHECK(!(s2 <= s1));
1200 CHECK(s2 > s1);
1201 CHECK(!(s1 > s2));
1202 CHECK(s2 >= s1);
1203 CHECK(!(s1 >= s2));
1204 }
1205 }
1206
1207 TEST(as_bytes)
1208 {
1209 int a[] = {1, 2, 3, 4};
1210
1211 {
1212 span<const int> s = a;
1213 CHECK(s.length() == 4);
1214 span<const byte> bs = as_bytes(s);
1215 CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
1216 CHECK(bs.length() == s.length_bytes());
1217 }
1218
1219 {
1220 span<int> s;
1221 auto bs = as_bytes(s);
1222 CHECK(bs.length() == s.length());
1223 CHECK(bs.length() == 0);
1224 CHECK(bs.size_bytes() == 0);
1225 CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
1226 CHECK(bs.data() == nullptr);
1227 }
1228
1229 {
1230 span<int> s = a;
1231 auto bs = as_bytes(s);
1232 CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
1233 CHECK(bs.length() == s.length_bytes());
1234 }
1235 }
1236
1237 TEST(as_writeable_bytes)
1238 {
1239 int a[] = {1, 2, 3, 4};
1240
1241 {
1242 #ifdef CONFIRM_COMPILATION_ERRORS
1243 // you should not be able to get writeable bytes for const objects
1244 span<const int> s = a;
1245 CHECK(s.length() == 4);
1246 span<const byte> bs = as_writeable_bytes(s);
1247 CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
1248 CHECK(bs.length() == s.length_bytes());
1249 #endif
1250 }
1251
1252 {
1253 span<int> s;
1254 auto bs = as_writeable_bytes(s);
1255 CHECK(bs.length() == s.length());
1256 CHECK(bs.length() == 0);
1257 CHECK(bs.size_bytes() == 0);
1258 CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
1259 CHECK(bs.data() == nullptr);
1260 }
1261
1262 {
1263 span<int> s = a;
1264 auto bs = as_writeable_bytes(s);
1265 CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
1266 CHECK(bs.length() == s.length_bytes());
1267 }
1268 }
1269
1270 TEST(fixed_size_conversions)
1271 {
1272 int arr[] = {1, 2, 3, 4};
1273
1274 // converting to an span from an equal size array is ok
1275 span<int, 4> s4 = arr;
1276 CHECK(s4.length() == 4);
1277
1278 // converting to dynamic_range is always ok
1279 {
1280 span<int> s = s4;
1281 CHECK(s.length() == s4.length());
1282 static_cast<void>(s);
1283 }
1284
1285 // initialization or assignment to static span that REDUCES size is NOT ok
1286 #ifdef CONFIRM_COMPILATION_ERRORS
1287 {
1288 span<int, 2> s = arr;
1289 }
1290 {
1291 span<int, 2> s2 = s4;
1292 static_cast<void>(s2);
1293 }
1294 #endif
1295
1296 // even when done dynamically
1297 {
1298 span<int> s = arr;
1299 auto f = [&]() {
1300 span<int, 2> s2 = s;
1301 static_cast<void>(s2);
1302 };
1303 CHECK_THROW(f(), fail_fast);
1304 }
1305
1306 // but doing so explicitly is ok
1307
1308 // you can convert statically
1309 {
1310 span<int, 2> s2 = {arr, 2};
1311 static_cast<void>(s2);
1312 }
1313 {
1314 span<int, 1> s1 = s4.first<1>();
1315 static_cast<void>(s1);
1316 }
1317
1318 // ...or dynamically
1319 {
1320 // NB: implicit conversion to span<int,1> from span<int>
1321 span<int, 1> s1 = s4.first(1);
1322 static_cast<void>(s1);
1323 }
1324
1325 // initialization or assignment to static span that requires size INCREASE is not ok.
1326 int arr2[2] = {1, 2};
1327
1328 #ifdef CONFIRM_COMPILATION_ERRORS
1329 {
1330 span<int, 4> s3 = arr2;
1331 }
1332 {
1333 span<int, 2> s2 = arr2;
1334 span<int, 4> s4a = s2;
1335 }
1336 #endif
1337 {
1338 auto f = [&]() {
1339 span<int, 4> s4 = {arr2, 2};
1340 static_cast<void>(s4);
1341 };
1342 CHECK_THROW(f(), fail_fast);
1343 }
1344
1345 // this should fail - we are trying to assign a small dynamic span to a fixed_size larger one
1346 span<int> av = arr2;
1347 auto f = [&]() {
1348 span<int, 4> s4 = av;
1349 static_cast<void>(s4);
1350 };
1351 CHECK_THROW(f(), fail_fast);
1352 }
1353
1354 TEST(interop_with_std_regex)
1355 {
1356 char lat[] = { '1', '2', '3', '4', '5', '6', 'E', 'F', 'G' };
1357 span<char> s = lat;
1358 auto f_it = s.begin() + 7;
1359
1360 std::match_results<span<char>::iterator> match;
1361
1362 std::regex_match(s.begin(), s.end(), match, std::regex(".*"));
1363 CHECK(match.ready());
1364 CHECK(!match.empty());
1365 CHECK(match[0].matched);
1366 CHECK(match[0].first == s.begin());
1367 CHECK(match[0].second == s.end());
1368
1369 std::regex_search(s.begin(), s.end(), match, std::regex("F"));
1370 CHECK(match.ready());
1371 CHECK(!match.empty());
1372 CHECK(match[0].matched);
1373 CHECK(match[0].first == f_it);
1374 CHECK(match[0].second == (f_it + 1));
1375 }
1376
1377 TEST(interop_with_gsl_at)
1378 {
1379 int arr[5] = {1, 2, 3, 4, 5};
1380 span<int> s{arr};
1381 CHECK(at(s,0) == 1 && at(s,1) == 2);
1382 }
1383 }
1384
main(int,const char * [])1385 int main(int, const char* []) { return UnitTest::RunAllTests(); }
1386