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