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