span_tests.cpp revision 0cf947db7760bf5756e4cb0d47c72a257ed527c5
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 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(from_nullptr_constructor) 78 { 79 { 80 span<int> s = nullptr; 81 CHECK(s.length() == 0 && s.data() == nullptr); 82 83 span<const int> cs = nullptr; 84 CHECK(cs.length() == 0 && cs.data() == nullptr); 85 } 86 87 { 88 span<int, 0> s = nullptr; 89 CHECK(s.length() == 0 && s.data() == nullptr); 90 91 span<const int, 0> cs = nullptr; 92 CHECK(cs.length() == 0 && cs.data() == nullptr); 93 } 94 95 { 96#ifdef CONFIRM_COMPILATION_ERRORS 97 span<int, 1> s = nullptr; 98 CHECK(s.length() == 1 && s.data() == nullptr); // explains why it can't compile 99#endif 100 } 101 102 { 103 span<int> s{nullptr}; 104 CHECK(s.length() == 0 && s.data() == nullptr); 105 106 span<const int> cs{nullptr}; 107 CHECK(cs.length() == 0 && cs.data() == nullptr); 108 } 109 110 { 111 span<int*> s{nullptr}; 112 CHECK(s.length() == 0 && s.data() == nullptr); 113 114 span<const int*> cs{nullptr}; 115 CHECK(cs.length() == 0 && cs.data() == nullptr); 116 } 117 } 118 119 TEST(from_nullptr_length_constructor) 120 { 121 { 122 span<int> s{nullptr, 0}; 123 CHECK(s.length() == 0 && s.data() == nullptr); 124 125 span<const int> cs{nullptr, 0}; 126 CHECK(cs.length() == 0 && cs.data() == nullptr); 127 } 128 129 { 130 span<int, 0> s{nullptr, 0}; 131 CHECK(s.length() == 0 && s.data() == nullptr); 132 133 span<const int, 0> cs{nullptr, 0}; 134 CHECK(cs.length() == 0 && cs.data() == nullptr); 135 } 136 137 { 138#ifdef CONFIRM_COMPILATION_ERRORS 139 span<int, 1> s{nullptr, 0}; 140 CHECK(s.length() == 1 && s.data() == nullptr); // explains why it can't compile 141#endif 142 } 143 144 { 145 auto workaround_macro = []() { span<int> s{nullptr, 1}; }; 146 CHECK_THROW(workaround_macro(), fail_fast); 147 148 auto const_workaround_macro = []() { span<const int> cs{nullptr, 1}; }; 149 CHECK_THROW(const_workaround_macro(), fail_fast); 150 } 151 152 { 153 auto workaround_macro = []() { span<int, 0> s{nullptr, 1}; }; 154 CHECK_THROW(workaround_macro(), fail_fast); 155 156 auto const_workaround_macro = []() { span<const int, 0> s{nullptr, 1}; }; 157 CHECK_THROW(const_workaround_macro(), fail_fast); 158 } 159 160 { 161 span<int*> s{nullptr, 0}; 162 CHECK(s.length() == 0 && s.data() == nullptr); 163 164 span<const int*> cs{nullptr, 0}; 165 CHECK(cs.length() == 0 && cs.data() == nullptr); 166 } 167 } 168 169 TEST(from_element_constructor) 170 { 171 int i = 5; 172 173 { 174 span<int> s = i; 175 CHECK(s.length() == 1 && s.data() == &i); 176 CHECK(s[0] == 5); 177 178 span<const int> cs = i; 179 CHECK(cs.length() == 1 && cs.data() == &i); 180 CHECK(cs[0] == 5); 181 } 182 183 { 184#ifdef CONFIRM_COMPILATION_ERRORS 185 const j = 1; 186 span<int, 0> s = j; 187#endif 188 } 189 190 { 191#ifdef CONFIRM_COMPILATION_ERRORS 192 span<int, 0> s = i; 193 CHECK(s.length() == 0 && s.data() == &i); 194#endif 195 } 196 197 { 198 span<int, 1> s = i; 199 CHECK(s.length() == 1 && s.data() == &i); 200 CHECK(s[0] == 5); 201 } 202 203 { 204#ifdef CONFIRM_COMPILATION_ERRORS 205 span<int, 2> s = i; 206 CHECK(s.length() == 2 && s.data() == &i); 207#endif 208 } 209 210 { 211#ifdef CONFIRM_COMPILATION_ERRORS 212 auto get_a_temp = []() -> int { return 4; }; 213 auto use_a_span = [](span<int> s) { (void) s; }; 214 use_a_span(get_a_temp()); 215#endif 216 } 217 } 218 219 TEST(from_pointer_length_constructor) 220 { 221 int arr[4] = {1, 2, 3, 4}; 222 223 { 224 span<int> s{&arr[0], 2}; 225 CHECK(s.length() == 2 && s.data() == &arr[0]); 226 CHECK(s[0] == 1 && s[1] == 2); 227 } 228 229 { 230 span<int, 2> s{&arr[0], 2}; 231 CHECK(s.length() == 2 && s.data() == &arr[0]); 232 CHECK(s[0] == 1 && s[1] == 2); 233 } 234 235 { 236 int* p = nullptr; 237 span<int> s{p, 0}; 238 CHECK(s.length() == 0 && s.data() == nullptr); 239 } 240 241 { 242 int* p = nullptr; 243 auto workaround_macro = [=]() { span<int> s{p, 2}; }; 244 CHECK_THROW(workaround_macro(), fail_fast); 245 } 246 } 247 248 TEST(from_pointer_pointer_constructor) 249 { 250 int arr[4] = {1, 2, 3, 4}; 251 252 { 253 span<int> s{&arr[0], &arr[2]}; 254 CHECK(s.length() == 2 && s.data() == &arr[0]); 255 CHECK(s[0] == 1 && s[1] == 2); 256 } 257 258 { 259 span<int, 2> s{&arr[0], &arr[2]}; 260 CHECK(s.length() == 2 && s.data() == &arr[0]); 261 CHECK(s[0] == 1 && s[1] == 2); 262 } 263 264 { 265 span<int> s{&arr[0], &arr[0]}; 266 CHECK(s.length() == 0 && s.data() == &arr[0]); 267 } 268 269 { 270 span<int, 0> s{&arr[0], &arr[0]}; 271 CHECK(s.length() == 0 && s.data() == &arr[0]); 272 } 273 274 { 275 auto workaround_macro = [&]() { span<int> s{&arr[1], &arr[0]}; }; 276 CHECK_THROW(workaround_macro(), fail_fast); 277 } 278 279 { 280 int* p = nullptr; 281 auto workaround_macro = [&]() { span<int> s{&arr[0], p}; }; 282 CHECK_THROW(workaround_macro(), fail_fast); 283 } 284 285 { 286 int* p = nullptr; 287 auto workaround_macro = [&]() { span<int> s{p, p}; }; 288 CHECK_THROW(workaround_macro(), fail_fast); 289 } 290 291 { 292 int* p = nullptr; 293 auto workaround_macro = [&]() { span<int> s{&arr[0], p}; }; 294 CHECK_THROW(workaround_macro(), fail_fast); 295 } 296 } 297 298 TEST(from_array_constructor) 299 { 300 int arr[5] = {1, 2, 3, 4, 5}; 301 302 { 303 span<int> s{arr}; 304 CHECK(s.length() == 5 && s.data() == &arr[0]); 305 } 306 307 { 308 span<int, 5> s{arr}; 309 CHECK(s.length() == 5 && s.data() == &arr[0]); 310 } 311 312 { 313#ifdef CONFIRM_COMPILATION_ERRORS 314 span<int, 6> s{arr}; 315#endif 316 } 317 318 { 319 span<int, 0> s{arr}; 320 CHECK(s.length() == 0 && s.data() == &arr[0]); 321 } 322 323 int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; 324 325 { 326 span<int> s{arr2d}; 327 CHECK(s.length() == 6 && s.data() == &arr2d[0][0]); 328 CHECK(s[0] == 1 && s[5] == 6); 329 } 330 331 { 332 span<int, 0> s{arr2d}; 333 CHECK(s.length() == 0 && s.data() == &arr2d[0][0]); 334 } 335 336 { 337#ifdef CONFIRM_COMPILATION_ERRORS 338 span<int, 5> s{arr2d}; 339#endif 340 } 341 342 { 343 span<int, 6> s{arr2d}; 344 CHECK(s.length() == 6 && s.data() == &arr2d[0][0]); 345 CHECK(s[0] == 1 && s[5] == 6); 346 } 347 348 { 349#ifdef CONFIRM_COMPILATION_ERRORS 350 span<int, 7> s{arr2d}; 351#endif 352 } 353 354 { 355 span<int[3]> s{arr2d[0]}; 356 CHECK(s.length() == 1 && s.data() == &arr2d[0]); 357 } 358 359 { 360 span<int, 2, 3> s{arr2d}; 361 CHECK(s.length() == 6 && s.data() == &arr2d[0][0]); 362 auto workaround_macro = [&]() { return s[{1, 2}] == 6; }; 363 CHECK(workaround_macro()); 364 } 365 366 { 367#ifdef CONFIRM_COMPILATION_ERRORS 368 span<int, 3, 3> s{arr2d}; 369#endif 370 } 371 372 int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; 373 374 { 375 span<int> s{arr3d}; 376 CHECK(s.length() == 12 && s.data() == &arr3d[0][0][0]); 377 CHECK(s[0] == 1 && s[11] == 12); 378 } 379 380 { 381 span<int, 0> s{arr3d}; 382 CHECK(s.length() == 0 && s.data() == &arr3d[0][0][0]); 383 } 384 385 { 386#ifdef CONFIRM_COMPILATION_ERRORS 387 span<int, 11> s{arr3d}; 388#endif 389 } 390 391 { 392 span<int, 12> s{arr3d}; 393 CHECK(s.length() == 12 && s.data() == &arr3d[0][0][0]); 394 CHECK(s[0] == 1 && s[5] == 6); 395 } 396 397 { 398#ifdef CONFIRM_COMPILATION_ERRORS 399 span<int, 13> s{arr3d}; 400#endif 401 } 402 403 { 404 span<int[3][2]> s{arr3d[0]}; 405 CHECK(s.length() == 1 && s.data() == &arr3d[0]); 406 } 407 408 { 409 span<int, 3, 2, 2> s{arr3d}; 410 CHECK(s.length() == 12 && s.data() == &arr3d[0][0][0]); 411 auto workaround_macro = [&]() { return s[{2, 1, 0}] == 11; }; 412 CHECK(workaround_macro()); 413 } 414 415 { 416#ifdef CONFIRM_COMPILATION_ERRORS 417 span<int, 3, 3, 3> s{arr3d}; 418#endif 419 } 420 } 421 422 TEST(from_dynamic_array_constructor) 423 { 424 double(*arr)[3][4] = new double[100][3][4]; 425 426 { 427 span<double, dynamic_range, 3, 4> s(arr, 10); 428 CHECK(s.length() == 120 && s.data() == &arr[0][0][0]); 429 CHECK_THROW(s[10][3][4], fail_fast); 430 } 431 432 { 433 span<double, dynamic_range, 4, 3> s(arr, 10); 434 CHECK(s.length() == 120 && s.data() == &arr[0][0][0]); 435 } 436 437 { 438 span<double> s(arr, 10); 439 CHECK(s.length() == 120 && s.data() == &arr[0][0][0]); 440 } 441 442 { 443 span<double, dynamic_range, 3, 4> s(arr, 0); 444 CHECK(s.length() == 0 && s.data() == &arr[0][0][0]); 445 } 446 447 delete[] arr; 448 } 449 450 TEST(from_std_array_constructor) 451 { 452 std::array<int, 4> arr = {1, 2, 3, 4}; 453 454 { 455 span<int> s{arr}; 456 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()); 457 458 span<const int> cs{arr}; 459 CHECK(cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data()); 460 } 461 462 { 463 span<int, 4> s{arr}; 464 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()); 465 466 span<const int, 4> cs{arr}; 467 CHECK(cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data()); 468 } 469 470 { 471 span<int, 2> s{arr}; 472 CHECK(s.size() == 2 && s.data() == arr.data()); 473 474 span<const int, 2> cs{arr}; 475 CHECK(cs.size() == 2 && cs.data() == arr.data()); 476 } 477 478 { 479 span<int, 0> s{arr}; 480 CHECK(s.size() == 0 && s.data() == arr.data()); 481 482 span<const int, 0> cs{arr}; 483 CHECK(cs.size() == 0 && cs.data() == arr.data()); 484 } 485 486 // TODO This is currently an unsupported scenario. We will come back to it as we revise 487 // the multidimensional interface and what transformations between dimensionality look like 488 //{ 489 // span<int, 2, 2> s{arr}; 490 // CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()); 491 //} 492 493 { 494#ifdef CONFIRM_COMPILATION_ERRORS 495 span<int, 5> s{arr}; 496#endif 497 } 498 499 { 500#ifdef CONFIRM_COMPILATION_ERRORS 501 auto get_an_array = []() { return std::array<int, 4>{1, 2, 3, 4}; }; 502 auto take_a_span = [](span<int> s) { (void) s; }; 503 // try to take a temporary std::array 504 take_a_span(get_an_array()); 505#endif 506 } 507 } 508 509 TEST(from_const_std_array_constructor) 510 { 511 const std::array<int, 4> arr = {1, 2, 3, 4}; 512 513 { 514 span<const int> s{arr}; 515 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()); 516 } 517 518 { 519 span<const int, 4> s{arr}; 520 CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()); 521 } 522 523 { 524 span<const int, 2> s{arr}; 525 CHECK(s.size() == 2 && s.data() == arr.data()); 526 } 527 528 { 529 span<const int, 0> s{arr}; 530 CHECK(s.size() == 0 && s.data() == arr.data()); 531 } 532 533 // TODO This is currently an unsupported scenario. We will come back to it as we revise 534 // the multidimensional interface and what transformations between dimensionality look like 535 //{ 536 // span<int, 2, 2> s{arr}; 537 // CHECK(s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()); 538 //} 539 540 { 541#ifdef CONFIRM_COMPILATION_ERRORS 542 span<const int, 5> s{arr}; 543#endif 544 } 545 546 { 547#ifdef CONFIRM_COMPILATION_ERRORS 548 auto get_an_array = []() -> const std::array<int, 4> { return {1, 2, 3, 4}; }; 549 auto take_a_span = [](span<const int> s) { (void) s; }; 550 // try to take a temporary std::array 551 take_a_span(get_an_array()); 552#endif 553 } 554 } 555 556 TEST(from_container_constructor) 557 { 558 std::vector<int> v = {1, 2, 3}; 559 const std::vector<int> cv = v; 560 561 { 562 span<int> s{v}; 563 CHECK(s.size() == narrow_cast<std::ptrdiff_t>(v.size()) && s.data() == v.data()); 564 565 span<const int> cs{v}; 566 CHECK(cs.size() == narrow_cast<std::ptrdiff_t>(v.size()) && cs.data() == v.data()); 567 } 568 569 std::string str = "hello"; 570 const std::string cstr = "hello"; 571 572 { 573#ifdef CONFIRM_COMPILATION_ERRORS 574 span<char> s{str}; 575 CHECK(s.size() == narrow_cast<std::ptrdiff_t>(str.size()) && s.data() == str.data()); 576#endif 577 span<const char> cs{str}; 578 CHECK(cs.size() == narrow_cast<std::ptrdiff_t>(str.size()) && cs.data() == str.data()); 579 } 580 581 { 582#ifdef CONFIRM_COMPILATION_ERRORS 583 span<char> s{cstr}; 584#endif 585 span<const char> cs{cstr}; 586 CHECK(cs.size() == narrow_cast<std::ptrdiff_t>(cstr.size()) && 587 cs.data() == cstr.data()); 588 } 589 590 { 591#ifdef CONFIRM_COMPILATION_ERRORS 592 auto get_temp_vector = []() -> std::vector<int> { return {}; }; 593 auto use_span = [](span<int> s) { (void) s; }; 594 use_span(get_temp_vector()); 595#endif 596 } 597 598 { 599#ifdef CONFIRM_COMPILATION_ERRORS 600 auto get_temp_string = []() -> std::string { return {}; }; 601 auto use_span = [](span<char> s) { (void) s; }; 602 use_span(get_temp_string()); 603#endif 604 } 605 606 { 607#ifdef CONFIRM_COMPILATION_ERRORS 608 auto get_temp_vector = []() -> const std::vector<int> { return {}; }; 609 auto use_span = [](span<const char> s) { (void) s; }; 610 use_span(get_temp_vector()); 611#endif 612 } 613 614 { 615#ifdef CONFIRM_COMPILATION_ERRORS 616 auto get_temp_string = []() -> const std::string { return {}; }; 617 auto use_span = [](span<const char> s) { (void) s; }; 618 use_span(get_temp_string()); 619#endif 620 } 621 622 { 623#ifdef CONFIRM_COMPILATION_ERRORS 624 std::map<int, int> m; 625 span<int> s{m}; 626#endif 627 } 628 } 629 630 TEST(from_convertible_span_constructor) 631 { 632#ifdef CONFIRM_COMPILATION_ERRORS 633 span<int, 7, 4, 2> av1(nullptr, b1); 634 635 auto f = [&]() { span<int, 7, 4, 2> av1(nullptr); }; 636 CHECK_THROW(f(), fail_fast); 637#endif 638 639#ifdef CONFIRM_COMPILATION_ERRORS 640 static_bounds<size_t, 7, dynamic_range, 2> b12(b11); 641 b12 = b11; 642 b11 = b12; 643 644 span<int, dynamic_range> av1 = nullptr; 645 span<int, 7, dynamic_range, 2> av2(av1); 646 span<int, 7, 4, 2> av2(av1); 647#endif 648 649 span<DerivedClass> avd; 650#ifdef CONFIRM_COMPILATION_ERRORS 651 span<BaseClass> avb = avd; 652#endif 653 span<const DerivedClass> avcd = avd; 654 (void) avcd; 655 } 656 657 TEST(copy_move_and_assignment) 658 { 659 span<int> s1; 660 CHECK(s1.empty()); 661 662 int arr[] = {3, 4, 5}; 663 664 span<const int> s2 = arr; 665 CHECK(s2.length() == 3 && s2.data() == &arr[0]); 666 667 s2 = s1; 668 CHECK(s2.empty()); 669 670 auto get_temp_span = [&]() -> span<int> { return {&arr[1], 2}; }; 671 auto use_span = [&](span<const int> s) { CHECK(s.length() == 2 && s.data() == &arr[1]); }; 672 use_span(get_temp_span()); 673 674 s1 = get_temp_span(); 675 CHECK(s1.length() == 2 && s1.data() == &arr[1]); 676 } 677 678 template <class Bounds> 679 void fn(const Bounds&) 680 { 681 static_assert(Bounds::static_size == 60, "static bounds is wrong size"); 682 } 683 TEST(as_span_reshape) 684 { 685 int a[3][4][5]; 686 auto av = as_span(a); 687 fn(av.bounds()); 688 auto av2 = as_span(av, dim<60>()); 689 auto av3 = as_span(av2, dim<3>(), dim<4>(), dim<5>()); 690 auto av4 = as_span(av3, dim<4>(), dim<>(3), dim<5>()); 691 auto av5 = as_span(av4, dim<3>(), dim<4>(), dim<5>()); 692 auto av6 = as_span(av5, dim<12>(), dim<>(5)); 693 694 fill(av6.begin(), av6.end(), 1); 695 696 auto av7 = as_bytes(av6); 697 698 auto av8 = as_span<int>(av7); 699 700 CHECK(av8.size() == av6.size()); 701 for (auto i = 0; i < av8.size(); i++) { 702 CHECK(av8[i] == 1); 703 } 704 } 705 706 TEST(first) 707 { 708 int arr[5] = {1, 2, 3, 4, 5}; 709 710 { 711 span<int, 5> av = arr; 712 CHECK((av.first<2>().bounds() == static_bounds<2>())); 713 CHECK(av.first<2>().length() == 2); 714 CHECK(av.first(2).length() == 2); 715 } 716 717 { 718 span<int, 5> av = arr; 719 CHECK((av.first<0>().bounds() == static_bounds<0>())); 720 CHECK(av.first<0>().length() == 0); 721 CHECK(av.first(0).length() == 0); 722 } 723 724 { 725 span<int, 5> av = arr; 726 CHECK((av.first<5>().bounds() == static_bounds<5>())); 727 CHECK(av.first<5>().length() == 5); 728 CHECK(av.first(5).length() == 5); 729 } 730 731 { 732 span<int, 5> av = arr; 733#ifdef CONFIRM_COMPILATION_ERRORS 734 CHECK(av.first<6>().bounds() == static_bounds<6>()); 735 CHECK(av.first<6>().length() == 6); 736 CHECK(av.first<-1>().length() == -1); 737#endif 738 CHECK_THROW(av.first(6).length(), fail_fast); 739 } 740 741 { 742 span<int, dynamic_range> av; 743 CHECK((av.first<0>().bounds() == static_bounds<0>())); 744 CHECK(av.first<0>().length() == 0); 745 CHECK(av.first(0).length() == 0); 746 } 747 } 748 749 TEST(last) 750 { 751 int arr[5] = {1, 2, 3, 4, 5}; 752 753 { 754 span<int, 5> av = arr; 755 CHECK((av.last<2>().bounds() == static_bounds<2>())); 756 CHECK(av.last<2>().length() == 2); 757 CHECK(av.last(2).length() == 2); 758 } 759 760 { 761 span<int, 5> av = arr; 762 CHECK((av.last<0>().bounds() == static_bounds<0>())); 763 CHECK(av.last<0>().length() == 0); 764 CHECK(av.last(0).length() == 0); 765 } 766 767 { 768 span<int, 5> av = arr; 769 CHECK((av.last<5>().bounds() == static_bounds<5>())); 770 CHECK(av.last<5>().length() == 5); 771 CHECK(av.last(5).length() == 5); 772 } 773 774 { 775 span<int, 5> av = arr; 776#ifdef CONFIRM_COMPILATION_ERRORS 777 CHECK((av.last<6>().bounds() == static_bounds<6>())); 778 CHECK(av.last<6>().length() == 6); 779#endif 780 CHECK_THROW(av.last(6).length(), fail_fast); 781 } 782 783 { 784 span<int, dynamic_range> av; 785 CHECK((av.last<0>().bounds() == static_bounds<0>())); 786 CHECK(av.last<0>().length() == 0); 787 CHECK(av.last(0).length() == 0); 788 } 789 } 790 791 TEST(subspan) 792 { 793 int arr[5] = {1, 2, 3, 4, 5}; 794 795 { 796 span<int, 5> av = arr; 797 CHECK((av.subspan<2, 2>().bounds() == static_bounds<2>())); 798 CHECK((av.subspan<2, 2>().length() == 2)); 799 CHECK(av.subspan(2, 2).length() == 2); 800 CHECK(av.subspan(2, 3).length() == 3); 801 } 802 803 { 804 span<int, 5> av = arr; 805 CHECK((av.subspan<0, 0>().bounds() == static_bounds<0>())); 806 CHECK((av.subspan<0, 0>().length() == 0)); 807 CHECK(av.subspan(0, 0).length() == 0); 808 } 809 810 { 811 span<int, 5> av = arr; 812 CHECK((av.subspan<0, 5>().bounds() == static_bounds<5>())); 813 CHECK((av.subspan<0, 5>().length() == 5)); 814 CHECK(av.subspan(0, 5).length() == 5); 815 CHECK_THROW(av.subspan(0, 6).length(), fail_fast); 816 CHECK_THROW(av.subspan(1, 5).length(), fail_fast); 817 } 818 819 { 820 span<int, 5> av = arr; 821 CHECK((av.subspan<5, 0>().bounds() == static_bounds<0>())); 822 CHECK((av.subspan<5, 0>().length() == 0)); 823 CHECK(av.subspan(5, 0).length() == 0); 824 CHECK_THROW(av.subspan(6, 0).length(), fail_fast); 825 } 826 827 { 828 span<int, dynamic_range> av; 829 CHECK((av.subspan<0, 0>().bounds() == static_bounds<0>())); 830 CHECK((av.subspan<0, 0>().length() == 0)); 831 CHECK(av.subspan(0, 0).length() == 0); 832 CHECK_THROW((av.subspan<1, 0>().length()), fail_fast); 833 } 834 835 { 836 span<int> av; 837 CHECK(av.subspan(0).length() == 0); 838 CHECK_THROW(av.subspan(1).length(), fail_fast); 839 } 840 841 { 842 span<int> av = arr; 843 CHECK(av.subspan(0).length() == 5); 844 CHECK(av.subspan(1).length() == 4); 845 CHECK(av.subspan(4).length() == 1); 846 CHECK(av.subspan(5).length() == 0); 847 CHECK_THROW(av.subspan(6).length(), fail_fast); 848 auto av2 = av.subspan(1); 849 for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2); 850 } 851 852 { 853 span<int, 5> av = arr; 854 CHECK(av.subspan(0).length() == 5); 855 CHECK(av.subspan(1).length() == 4); 856 CHECK(av.subspan(4).length() == 1); 857 CHECK(av.subspan(5).length() == 0); 858 CHECK_THROW(av.subspan(6).length(), fail_fast); 859 auto av2 = av.subspan(1); 860 for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2); 861 } 862 } 863 864 TEST(rank) 865 { 866 int arr[2] = {1, 2}; 867 868 { 869 span<int> s; 870 CHECK(s.rank() == 1); 871 } 872 873 { 874 span<int, 2> s = arr; 875 CHECK(s.rank() == 1); 876 } 877 878 int arr2d[1][1] = {}; 879 { 880 span<int, 1, 1> s = arr2d; 881 CHECK(s.rank() == 2); 882 } 883 } 884 885 TEST(extent) 886 { 887 { 888 span<int> s; 889 CHECK(s.extent() == 0); 890 CHECK(s.extent(0) == 0); 891 CHECK_THROW(s.extent(1), fail_fast); 892#ifdef CONFIRM_COMPILATION_ERRORS 893 CHECK(s.extent<1>() == 0); 894#endif 895 } 896 897 { 898 span<int, 0> s; 899 CHECK(s.extent() == 0); 900 CHECK(s.extent(0) == 0); 901 CHECK_THROW(s.extent(1), fail_fast); 902 } 903 904 { 905 int arr2d[1][2] = {}; 906 907 span<int, 1, 2> s = arr2d; 908 CHECK(s.extent() == 1); 909 CHECK(s.extent<0>() == 1); 910 CHECK(s.extent<1>() == 2); 911 CHECK(s.extent(0) == 1); 912 CHECK(s.extent(1) == 2); 913 CHECK_THROW(s.extent(3), fail_fast); 914 } 915 916 { 917 int arr2d[1][2] = {}; 918 919 span<int, 0, 2> s = arr2d; 920 CHECK(s.extent() == 0); 921 CHECK(s.extent<0>() == 0); 922 CHECK(s.extent<1>() == 2); 923 CHECK(s.extent(0) == 0); 924 CHECK(s.extent(1) == 2); 925 CHECK_THROW(s.extent(3), fail_fast); 926 } 927 } 928 929 TEST(operator_function_call) 930 { 931 int arr[4] = {1, 2, 3, 4}; 932 933 { 934 span<int> s = arr; 935 CHECK(s(0) == 1); 936 CHECK_THROW(s(5), fail_fast); 937 } 938 939 int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; 940 941 { 942 span<int, 2, 3> s = arr2d; 943 CHECK(s(0, 0) == 1); 944 CHECK(s(1, 2) == 6); 945 } 946 } 947 948 TEST(comparison_operators) 949 { 950 { 951 int arr[10][2]; 952 auto s1 = as_span(arr); 953 span<const int, dynamic_range, 2> s2 = s1; 954 955 CHECK(s1 == s2); 956 957 span<int, 20> s3 = as_span(s1, dim<>(20)); 958 CHECK(s3 == s2 && s3 == s1); 959 } 960 961 { 962 auto s1 = nullptr; 963 auto s2 = nullptr; 964 CHECK(s1 == s2); 965 CHECK(!(s1 != s2)); 966 CHECK(!(s1 < s2)); 967 CHECK(s1 <= s2); 968 CHECK(!(s1 > s2)); 969 CHECK(s1 >= s2); 970 CHECK(s2 == s1); 971 CHECK(!(s2 != s1)); 972 CHECK(!(s2 < s1)); 973 CHECK(s2 <= s1); 974 CHECK(!(s2 > s1)); 975 CHECK(s2 >= s1); 976 } 977 978 { 979 int arr[] = {2, 1}; // bigger 980 981 span<int> s1 = nullptr; 982 span<int> s2 = arr; 983 984 CHECK(s1 != s2); 985 CHECK(s2 != s1); 986 CHECK(!(s1 == s2)); 987 CHECK(!(s2 == s1)); 988 CHECK(s1 < s2); 989 CHECK(!(s2 < s1)); 990 CHECK(s1 <= s2); 991 CHECK(!(s2 <= s1)); 992 CHECK(s2 > s1); 993 CHECK(!(s1 > s2)); 994 CHECK(s2 >= s1); 995 CHECK(!(s1 >= s2)); 996 } 997 998 { 999 int arr1[] = {1, 2}; 1000 int arr2[] = {1, 2}; 1001 span<int> s1 = arr1; 1002 span<int> s2 = arr2; 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[] = {1, 2, 3}; 1020 1021 span<int> s1 = {&arr[0], 2}; // shorter 1022 span<int> s2 = arr; // longer 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}; // smaller 1040 int arr2[] = {2, 1}; // bigger 1041 1042 span<int> s1 = arr1; 1043 span<int> s2 = arr2; 1044 1045 CHECK(s1 != s2); 1046 CHECK(s2 != s1); 1047 CHECK(!(s1 == s2)); 1048 CHECK(!(s2 == s1)); 1049 CHECK(s1 < s2); 1050 CHECK(!(s2 < s1)); 1051 CHECK(s1 <= s2); 1052 CHECK(!(s2 <= s1)); 1053 CHECK(s2 > s1); 1054 CHECK(!(s1 > s2)); 1055 CHECK(s2 >= s1); 1056 CHECK(!(s1 >= s2)); 1057 } 1058 } 1059 1060 TEST(basics) 1061 { 1062 auto ptr = as_span(new int[10], 10); 1063 fill(ptr.begin(), ptr.end(), 99); 1064 for (int num : ptr) { 1065 CHECK(num == 99); 1066 } 1067 1068 delete[] ptr.data(); 1069 } 1070 1071 TEST(bounds_checks) 1072 { 1073 int arr[10][2]; 1074 auto av = as_span(arr); 1075 1076 fill(begin(av), end(av), 0); 1077 1078 av[2][0] = 1; 1079 av[1][1] = 3; 1080 1081 // out of bounds 1082 CHECK_THROW(av[1][3] = 3, fail_fast); 1083 CHECK_THROW((av[{1, 3}] = 3), fail_fast); 1084 1085 CHECK_THROW(av[10][2], fail_fast); 1086 CHECK_THROW((av[{10, 2}]), fail_fast); 1087 } 1088 1089 void overloaded_func(span<const int, dynamic_range, 3, 5> exp, int expected_value) 1090 { 1091 for (auto val : exp) { 1092 CHECK(val == expected_value); 1093 } 1094 } 1095 1096 void overloaded_func(span<const char, dynamic_range, 3, 5> exp, char expected_value) 1097 { 1098 for (auto val : exp) { 1099 CHECK(val == expected_value); 1100 } 1101 } 1102 1103 void fixed_func(span<int, 3, 3, 5> exp, int expected_value) 1104 { 1105 for (auto val : exp) { 1106 CHECK(val == expected_value); 1107 } 1108 } 1109 1110 TEST(span_parameter_test) 1111 { 1112 auto data = new int[4][3][5]; 1113 1114 auto av = as_span(data, 4); 1115 1116 CHECK(av.size() == 60); 1117 1118 fill(av.begin(), av.end(), 34); 1119 1120 int count = 0; 1121 for_each(av.rbegin(), av.rend(), [&](int val) { count += val; }); 1122 CHECK(count == 34 * 60); 1123 overloaded_func(av, 34); 1124 1125 overloaded_func(as_span(av, dim<>(4), dim<>(3), dim<>(5)), 34); 1126 1127 // fixed_func(av, 34); 1128 delete[] data; 1129 } 1130 1131 TEST(md_access) 1132 { 1133 auto width = 5, height = 20; 1134 1135 auto imgSize = width * height; 1136 auto image_ptr = new int[imgSize][3]; 1137 1138 // size check will be done 1139 auto image_view = 1140 as_span(as_span(image_ptr, imgSize), dim<>(height), dim<>(width), dim<3>()); 1141 1142 iota(image_view.begin(), image_view.end(), 1); 1143 1144 int expected = 0; 1145 for (auto i = 0; i < height; i++) { 1146 for (auto j = 0; j < width; j++) { 1147 CHECK(expected + 1 == image_view[i][j][0]); 1148 CHECK(expected + 2 == image_view[i][j][1]); 1149 CHECK(expected + 3 == image_view[i][j][2]); 1150 1151 auto val = image_view[{i, j, 0}]; 1152 CHECK(expected + 1 == val); 1153 val = image_view[{i, j, 1}]; 1154 CHECK(expected + 2 == val); 1155 val = image_view[{i, j, 2}]; 1156 CHECK(expected + 3 == val); 1157 1158 expected += 3; 1159 } 1160 } 1161 } 1162 1163 TEST(as_span) 1164 { 1165 { 1166 int* arr = new int[150]; 1167 1168 auto av = as_span(arr, dim<10>(), dim<>(3), dim<5>()); 1169 1170 fill(av.begin(), av.end(), 24); 1171 overloaded_func(av, 24); 1172 1173 delete[] arr; 1174 1175 array<int, 15> stdarr{0}; 1176 auto av2 = as_span(stdarr); 1177 overloaded_func(as_span(av2, dim<>(1), dim<3>(), dim<5>()), 0); 1178 1179 string str = "ttttttttttttttt"; // size = 15 1180 auto t = str.data(); 1181 (void) t; 1182 auto av3 = as_span(str); 1183 overloaded_func(as_span(av3, dim<>(1), dim<3>(), dim<5>()), 't'); 1184 } 1185 1186 { 1187 string str; 1188 span<char> strspan = as_span(str); 1189 (void) strspan; 1190 const string cstr; 1191 span<const char> cstrspan = as_span(cstr); 1192 (void) cstrspan; 1193 } 1194 1195 { 1196 int a[3][4][5]; 1197 auto av = as_span(a); 1198 const int(*b)[4][5]; 1199 b = a; 1200 auto bv = as_span(b, 3); 1201 1202 CHECK(av == bv); 1203 1204 const std::array<double, 3> arr = {0.0, 0.0, 0.0}; 1205 auto cv = as_span(arr); 1206 (void) cv; 1207 1208 vector<float> vec(3); 1209 auto dv = as_span(vec); 1210 (void) dv; 1211 1212#ifdef CONFIRM_COMPILATION_ERRORS 1213 auto dv2 = as_span(std::move(vec)); 1214#endif 1215 } 1216 } 1217 1218 TEST(empty_spans) 1219 { 1220 { 1221 span<int, 0> empty_av(nullptr); 1222 1223 CHECK(empty_av.bounds().index_bounds() == index<1>{0}); 1224 CHECK_THROW(empty_av[0], fail_fast); 1225 CHECK_THROW(empty_av.begin()[0], fail_fast); 1226 CHECK_THROW(empty_av.cbegin()[0], fail_fast); 1227 for (auto& v : empty_av) { 1228 (void) v; 1229 CHECK(false); 1230 } 1231 } 1232 1233 { 1234 span<int> empty_av = {}; 1235 CHECK(empty_av.bounds().index_bounds() == index<1>{0}); 1236 CHECK_THROW(empty_av[0], fail_fast); 1237 CHECK_THROW(empty_av.begin()[0], fail_fast); 1238 CHECK_THROW(empty_av.cbegin()[0], fail_fast); 1239 for (auto& v : empty_av) { 1240 (void) v; 1241 CHECK(false); 1242 } 1243 } 1244 } 1245 1246 TEST(index_constructor) 1247 { 1248 auto arr = new int[8]; 1249 for (int i = 0; i < 4; ++i) { 1250 arr[2 * i] = 4 + i; 1251 arr[2 * i + 1] = i; 1252 } 1253 1254 span<int, dynamic_range> av(arr, 8); 1255 1256 ptrdiff_t a[1] = {0}; 1257 index<1> i = a; 1258 1259 CHECK(av[i] == 4); 1260 1261 auto av2 = as_span(av, dim<4>(), dim<>(2)); 1262 ptrdiff_t a2[2] = {0, 1}; 1263 index<2> i2 = a2; 1264 1265 CHECK(av2[i2] == 0); 1266 CHECK(av2[0][i] == 4); 1267 1268 delete[] arr; 1269 } 1270 1271 TEST(index_constructors) 1272 { 1273 { 1274 // components of the same type 1275 index<3> i1(0, 1, 2); 1276 CHECK(i1[0] == 0); 1277 1278 // components of different types 1279 size_t c0 = 0; 1280 size_t c1 = 1; 1281 index<3> i2(c0, c1, 2); 1282 CHECK(i2[0] == 0); 1283 1284 // from array 1285 index<3> i3 = {0, 1, 2}; 1286 CHECK(i3[0] == 0); 1287 1288 // from other index of the same size type 1289 index<3> i4 = i3; 1290 CHECK(i4[0] == 0); 1291 1292 // default 1293 index<3> i7; 1294 CHECK(i7[0] == 0); 1295 1296 // default 1297 index<3> i9 = {}; 1298 CHECK(i9[0] == 0); 1299 } 1300 1301 { 1302 // components of the same type 1303 index<1> i1(0); 1304 CHECK(i1[0] == 0); 1305 1306 // components of different types 1307 size_t c0 = 0; 1308 index<1> i2(c0); 1309 CHECK(i2[0] == 0); 1310 1311 // from array 1312 index<1> i3 = {0}; 1313 CHECK(i3[0] == 0); 1314 1315 // from int 1316 index<1> i4 = 0; 1317 CHECK(i4[0] == 0); 1318 1319 // from other index of the same size type 1320 index<1> i5 = i3; 1321 CHECK(i5[0] == 0); 1322 1323 // default 1324 index<1> i8; 1325 CHECK(i8[0] == 0); 1326 1327 // default 1328 index<1> i9 = {}; 1329 CHECK(i9[0] == 0); 1330 } 1331 1332#ifdef CONFIRM_COMPILATION_ERRORS 1333 { 1334 index<3> i1(0, 1); 1335 index<3> i2(0, 1, 2, 3); 1336 index<3> i3 = {0}; 1337 index<3> i4 = {0, 1, 2, 3}; 1338 index<1> i5 = {0, 1}; 1339 } 1340#endif 1341 } 1342 1343 TEST(index_operations) 1344 { 1345 ptrdiff_t a[3] = {0, 1, 2}; 1346 ptrdiff_t b[3] = {3, 4, 5}; 1347 index<3> i = a; 1348 index<3> j = b; 1349 1350 CHECK(i[0] == 0); 1351 CHECK(i[1] == 1); 1352 CHECK(i[2] == 2); 1353 1354 { 1355 index<3> k = i + j; 1356 1357 CHECK(i[0] == 0); 1358 CHECK(i[1] == 1); 1359 CHECK(i[2] == 2); 1360 CHECK(k[0] == 3); 1361 CHECK(k[1] == 5); 1362 CHECK(k[2] == 7); 1363 } 1364 1365 { 1366 index<3> k = i * 3; 1367 1368 CHECK(i[0] == 0); 1369 CHECK(i[1] == 1); 1370 CHECK(i[2] == 2); 1371 CHECK(k[0] == 0); 1372 CHECK(k[1] == 3); 1373 CHECK(k[2] == 6); 1374 } 1375 1376 { 1377 index<3> k = 3 * i; 1378 1379 CHECK(i[0] == 0); 1380 CHECK(i[1] == 1); 1381 CHECK(i[2] == 2); 1382 CHECK(k[0] == 0); 1383 CHECK(k[1] == 3); 1384 CHECK(k[2] == 6); 1385 } 1386 1387 { 1388 index<2> k = details::shift_left(i); 1389 1390 CHECK(i[0] == 0); 1391 CHECK(i[1] == 1); 1392 CHECK(i[2] == 2); 1393 CHECK(k[0] == 1); 1394 CHECK(k[1] == 2); 1395 } 1396 } 1397 1398 void iterate_second_column(span<int, dynamic_range, dynamic_range> av) 1399 { 1400 auto length = av.size() / 2; 1401 1402 // view to the second column 1403 auto section = av.section({0, 1}, {length, 1}); 1404 1405 CHECK(section.size() == length); 1406 for (auto i = 0; i < section.size(); ++i) { 1407 CHECK(section[i][0] == av[i][1]); 1408 } 1409 1410 for (auto i = 0; i < section.size(); ++i) { 1411 auto idx = index<2>{i, 0}; // avoid braces inside the CHECK macro 1412 CHECK(section[idx] == av[i][1]); 1413 } 1414 1415 CHECK(section.bounds().index_bounds()[0] == length); 1416 CHECK(section.bounds().index_bounds()[1] == 1); 1417 for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) { 1418 for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) { 1419 auto idx = index<2>{i, j}; // avoid braces inside the CHECK macro 1420 CHECK(section[idx] == av[i][1]); 1421 } 1422 } 1423 1424 size_t check_sum = 0; 1425 for (auto i = 0; i < length; ++i) { 1426 check_sum += av[i][1]; 1427 } 1428 1429 { 1430 auto idx = 0; 1431 size_t sum = 0; 1432 for (auto num : section) { 1433 CHECK(num == av[idx][1]); 1434 sum += num; 1435 idx++; 1436 } 1437 1438 CHECK(sum == check_sum); 1439 } 1440 { 1441 size_t idx = length - 1; 1442 size_t sum = 0; 1443 for (auto iter = section.rbegin(); iter != section.rend(); ++iter) { 1444 CHECK(*iter == av[idx][1]); 1445 sum += *iter; 1446 idx--; 1447 } 1448 1449 CHECK(sum == check_sum); 1450 } 1451 } 1452 1453 TEST(span_section_iteration) 1454 { 1455 int arr[4][2] = {{4, 0}, {5, 1}, {6, 2}, {7, 3}}; 1456 1457 // static bounds 1458 { 1459 span<int, 4, 2> av = arr; 1460 iterate_second_column(av); 1461 } 1462 // first bound is dynamic 1463 { 1464 span<int, dynamic_range, 2> av = arr; 1465 iterate_second_column(av); 1466 } 1467 // second bound is dynamic 1468 { 1469 span<int, 4, dynamic_range> av = arr; 1470 iterate_second_column(av); 1471 } 1472 // both bounds are dynamic 1473 { 1474 span<int, dynamic_range, dynamic_range> av = arr; 1475 iterate_second_column(av); 1476 } 1477 } 1478 1479 TEST(dynamic_span_section_iteration) 1480 { 1481 auto height = 4, width = 2; 1482 auto size = height * width; 1483 1484 auto arr = new int[size]; 1485 for (auto i = 0; i < size; ++i) { 1486 arr[i] = i; 1487 } 1488 1489 auto av = as_span(arr, size); 1490 1491 // first bound is dynamic 1492 { 1493 span<int, dynamic_range, 2> av2 = as_span(av, dim<>(height), dim<>(width)); 1494 iterate_second_column(av2); 1495 } 1496 // second bound is dynamic 1497 { 1498 span<int, 4, dynamic_range> av2 = as_span(av, dim<>(height), dim<>(width)); 1499 iterate_second_column(av2); 1500 } 1501 // both bounds are dynamic 1502 { 1503 span<int, dynamic_range, dynamic_range> av2 = as_span(av, dim<>(height), dim<>(width)); 1504 iterate_second_column(av2); 1505 } 1506 1507 delete[] arr; 1508 } 1509 1510 TEST(span_structure_size) 1511 { 1512 double(*arr)[3][4] = new double[100][3][4]; 1513 span<double, dynamic_range, 3, 4> av1(arr, 10); 1514 1515 struct EffectiveStructure 1516 { 1517 double* v1; 1518 ptrdiff_t v2; 1519 }; 1520 CHECK(sizeof(av1) == sizeof(EffectiveStructure)); 1521 1522 CHECK_THROW(av1[10][3][4], fail_fast); 1523 1524 span<const double, dynamic_range, 6, 4> av2 = as_span(av1, dim<>(5), dim<6>(), dim<4>()); 1525 (void) av2; 1526 } 1527 1528 TEST(fixed_size_conversions) 1529 { 1530 int arr[] = {1, 2, 3, 4}; 1531 1532 // converting to an span from an equal size array is ok 1533 span<int, 4> av4 = arr; 1534 CHECK(av4.length() == 4); 1535 1536 // converting to dynamic_range a_v is always ok 1537 { 1538 span<int, dynamic_range> av = av4; 1539 (void) av; 1540 } 1541 { 1542 span<int, dynamic_range> av = arr; 1543 (void) av; 1544 } 1545 1546// initialization or assignment to static span that REDUCES size is NOT ok 1547#ifdef CONFIRM_COMPILATION_ERRORS 1548 { 1549 span<int, 2> av2 = arr; 1550 } 1551 { 1552 span<int, 2> av2 = av4; 1553 } 1554#endif 1555 1556 { 1557 span<int, dynamic_range> av = arr; 1558 span<int, 2> av2 = av; 1559 (void) av2; 1560 } 1561 1562#ifdef CONFIRM_COMPILATION_ERRORS 1563 { 1564 span<int, dynamic_range> av = arr; 1565 span<int, 2, 1> av2 = av.as_span(dim<2>(), dim<2>()); 1566 } 1567#endif 1568 1569 { 1570 span<int, dynamic_range> av = arr; 1571 span<int, 2, 1> av2 = as_span(av, dim<>(2), dim<>(2)); 1572 auto workaround_macro = [&]() { return av2[{1, 0}] == 2; }; 1573 CHECK(workaround_macro()); 1574 } 1575 1576 // but doing so explicitly is ok 1577 1578 // you can convert statically 1579 { 1580 span<int, 2> av2 = {arr, 2}; 1581 (void) av2; 1582 } 1583 { 1584 span<int, 1> av2 = av4.first<1>(); 1585 (void) av2; 1586 } 1587 1588 // ...or dynamically 1589 { 1590 // NB: implicit conversion to span<int,2> from span<int,dynamic_range> 1591 span<int, 1> av2 = av4.first(1); 1592 (void) av2; 1593 } 1594 1595 // initialization or assignment to static span that requires size INCREASE is not ok. 1596 int arr2[2] = {1, 2}; 1597 1598#ifdef CONFIRM_COMPILATION_ERRORS 1599 { 1600 span<int, 4> av4 = arr2; 1601 } 1602 { 1603 span<int, 2> av2 = arr2; 1604 span<int, 4> av4 = av2; 1605 } 1606#endif 1607 { 1608 auto f = [&]() { 1609 span<int, 4> av4 = {arr2, 2}; 1610 (void) av4; 1611 }; 1612 CHECK_THROW(f(), fail_fast); 1613 } 1614 1615 // this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one 1616 span<int, dynamic_range> av = arr2; 1617 auto f = [&]() { 1618 span<int, 4> av2 = av; 1619 (void) av2; 1620 }; 1621 CHECK_THROW(f(), fail_fast); 1622 } 1623 1624 TEST(as_writeable_bytes) 1625 { 1626 int a[] = {1, 2, 3, 4}; 1627 1628 { 1629#ifdef CONFIRM_COMPILATION_ERRORS 1630 // you should not be able to get writeable bytes for const objects 1631 span<const int, dynamic_range> av = a; 1632 auto wav = av.as_writeable_bytes(); 1633#endif 1634 } 1635 1636 { 1637 span<int, dynamic_range> av; 1638 auto wav = as_writeable_bytes(av); 1639 CHECK(wav.length() == av.length()); 1640 CHECK(wav.length() == 0); 1641 CHECK(wav.size_bytes() == 0); 1642 } 1643 1644 { 1645 span<int, dynamic_range> av = a; 1646 auto wav = as_writeable_bytes(av); 1647 CHECK(wav.data() == (byte*) &a[0]); 1648 CHECK(wav.length() == sizeof(a)); 1649 } 1650 } 1651 1652 TEST(iterator) 1653 { 1654 int a[] = {1, 2, 3, 4}; 1655 1656 { 1657 span<int, dynamic_range> av = a; 1658 auto wav = as_writeable_bytes(av); 1659 for (auto& b : wav) { 1660 b = byte(0); 1661 } 1662 for (size_t i = 0; i < 4; ++i) { 1663 CHECK(a[i] == 0); 1664 } 1665 } 1666 1667 { 1668 span<int, dynamic_range> av = a; 1669 for (auto& n : av) { 1670 n = 1; 1671 } 1672 for (size_t i = 0; i < 4; ++i) { 1673 CHECK(a[i] == 1); 1674 } 1675 } 1676 } 1677} 1678 1679int main(int, const char* []) { return UnitTest::RunAllTests(); } 1680