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