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