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