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