TestSpan.cpp (57425B)
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 // Adapted from 18 // https://github.com/Microsoft/GSL/blob/3819df6e378ffccf0e29465afe99c3b324c2aa70/tests/Span_tests.cpp 19 20 #include "gtest/gtest.h" 21 22 #include "mozilla/Array.h" 23 #include "mozilla/Span.h" 24 25 #include "nsString.h" 26 #include "nsTArray.h" 27 #include "mozilla/Range.h" 28 29 #include <type_traits> 30 31 #define SPAN_TEST(name) TEST(SpanTest, name) 32 #define CHECK_THROW(a, b) 33 34 using namespace mozilla; 35 36 static_assert(std::is_convertible_v<Range<int>, Span<const int>>, 37 "Range should convert into const"); 38 static_assert(std::is_convertible_v<Range<const int>, Span<const int>>, 39 "const Range should convert into const"); 40 static_assert(!std::is_convertible_v<Range<const int>, Span<int>>, 41 "Range should not drop const in conversion"); 42 static_assert(std::is_convertible_v<Span<int>, Range<const int>>, 43 "Span should convert into const"); 44 static_assert(std::is_convertible_v<Span<const int>, Range<const int>>, 45 "const Span should convert into const"); 46 static_assert(!std::is_convertible_v<Span<const int>, Range<int>>, 47 "Span should not drop const in conversion"); 48 static_assert(std::is_convertible_v<Span<const int>, Span<const int>>, 49 "const Span should convert into const"); 50 static_assert(std::is_convertible_v<Span<int>, Span<const int>>, 51 "Span should convert into const"); 52 static_assert(!std::is_convertible_v<Span<const int>, Span<int>>, 53 "Span should not drop const in conversion"); 54 static_assert(std::is_convertible_v<const nsTArray<int>, Span<const int>>, 55 "const nsTArray should convert into const"); 56 static_assert(std::is_convertible_v<nsTArray<int>, Span<const int>>, 57 "nsTArray should convert into const"); 58 static_assert(!std::is_convertible_v<const nsTArray<int>, Span<int>>, 59 "nsTArray should not drop const in conversion"); 60 static_assert(std::is_convertible_v<nsTArray<const int>, Span<const int>>, 61 "nsTArray should convert into const"); 62 static_assert(!std::is_convertible_v<nsTArray<const int>, Span<int>>, 63 "nsTArray should not drop const in conversion"); 64 65 static_assert(std::is_convertible_v<const std::vector<int>, Span<const int>>, 66 "const std::vector should convert into const"); 67 static_assert(std::is_convertible_v<std::vector<int>, Span<const int>>, 68 "std::vector should convert into const"); 69 static_assert(!std::is_convertible_v<const std::vector<int>, Span<int>>, 70 "std::vector should not drop const in conversion"); 71 72 /** 73 * Rust slice-compatible nullptr replacement value. 74 */ 75 #define SLICE_CONST_INT_PTR reinterpret_cast<const int*>(alignof(const int)) 76 77 /** 78 * Rust slice-compatible nullptr replacement value. 79 */ 80 #define SLICE_INT_PTR reinterpret_cast<int*>(alignof(int)) 81 82 /** 83 * Rust slice-compatible nullptr replacement value. 84 */ 85 #define SLICE_CONST_INT_PTR_PTR \ 86 reinterpret_cast<const int**>(alignof(const int*)) 87 88 /** 89 * Rust slice-compatible nullptr replacement value. 90 */ 91 #define SLICE_INT_PTR_PTR reinterpret_cast<int**>(alignof(int*)) 92 93 namespace { 94 struct BaseClass {}; 95 struct DerivedClass : BaseClass {}; 96 } // namespace 97 98 void AssertSpanOfThreeInts(Span<const int> s) { 99 ASSERT_EQ(s.size(), 3U); 100 ASSERT_EQ(s[0], 1); 101 ASSERT_EQ(s[1], 2); 102 ASSERT_EQ(s[2], 3); 103 } 104 105 void AssertSpanOfThreeChars(Span<const char> s) { 106 ASSERT_EQ(s.size(), 3U); 107 ASSERT_EQ(s[0], 'a'); 108 ASSERT_EQ(s[1], 'b'); 109 ASSERT_EQ(s[2], 'c'); 110 } 111 112 void AssertSpanOfThreeChar16s(Span<const char16_t> s) { 113 ASSERT_EQ(s.size(), 3U); 114 ASSERT_EQ(s[0], 'a'); 115 ASSERT_EQ(s[1], 'b'); 116 ASSERT_EQ(s[2], 'c'); 117 } 118 119 void AssertSpanOfThreeCharsViaString(const nsACString& aStr) { 120 AssertSpanOfThreeChars(aStr); 121 } 122 123 void AssertSpanOfThreeChar16sViaString(const nsAString& aStr) { 124 AssertSpanOfThreeChar16s(aStr); 125 } 126 127 SPAN_TEST(default_constructor) { 128 { 129 Span<int> s; 130 ASSERT_EQ(s.Length(), 0U); 131 ASSERT_EQ(s.data(), SLICE_INT_PTR); 132 133 Span<const int> cs; 134 ASSERT_EQ(cs.Length(), 0U); 135 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR); 136 } 137 138 { 139 Span<int, 0> s; 140 ASSERT_EQ(s.Length(), 0U); 141 ASSERT_EQ(s.data(), SLICE_INT_PTR); 142 143 Span<const int, 0> cs; 144 ASSERT_EQ(cs.Length(), 0U); 145 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR); 146 } 147 148 { 149 #ifdef CONFIRM_COMPILATION_ERRORS 150 Span<int, 1> s; 151 ASSERT_EQ(s.Length(), 1U); 152 ASSERT_EQ(s.data(), SLICE_INT_PTR); // explains why it can't compile 153 #endif 154 } 155 156 { 157 Span<int> s{}; 158 ASSERT_EQ(s.Length(), 0U); 159 ASSERT_EQ(s.data(), SLICE_INT_PTR); 160 161 Span<const int> cs{}; 162 ASSERT_EQ(cs.Length(), 0U); 163 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR); 164 } 165 } 166 167 SPAN_TEST(size_optimization) { 168 { 169 Span<int> s; 170 ASSERT_EQ(sizeof(s), sizeof(int*) + sizeof(size_t)); 171 } 172 173 { 174 Span<int, 0> s; 175 ASSERT_EQ(sizeof(s), sizeof(int*)); 176 } 177 } 178 179 SPAN_TEST(from_nullptr_constructor) { 180 { 181 Span<int> s = nullptr; 182 ASSERT_EQ(s.Length(), 0U); 183 ASSERT_EQ(s.data(), SLICE_INT_PTR); 184 185 Span<const int> cs = nullptr; 186 ASSERT_EQ(cs.Length(), 0U); 187 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR); 188 } 189 190 { 191 Span<int, 0> s = nullptr; 192 ASSERT_EQ(s.Length(), 0U); 193 ASSERT_EQ(s.data(), SLICE_INT_PTR); 194 195 Span<const int, 0> cs = nullptr; 196 ASSERT_EQ(cs.Length(), 0U); 197 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR); 198 } 199 200 { 201 #ifdef CONFIRM_COMPILATION_ERRORS 202 Span<int, 1> s = nullptr; 203 ASSERT_EQ(s.Length(), 1U); 204 ASSERT_EQ(s.data(), SLICE_INT_PTR); // explains why it can't compile 205 #endif 206 } 207 208 { 209 Span<int> s{nullptr}; 210 ASSERT_EQ(s.Length(), 0U); 211 ASSERT_EQ(s.data(), SLICE_INT_PTR); 212 213 Span<const int> cs{nullptr}; 214 ASSERT_EQ(cs.Length(), 0U); 215 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR); 216 } 217 218 { 219 Span<int*> s{nullptr}; 220 ASSERT_EQ(s.Length(), 0U); 221 ASSERT_EQ(s.data(), SLICE_INT_PTR_PTR); 222 223 Span<const int*> cs{nullptr}; 224 ASSERT_EQ(cs.Length(), 0U); 225 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR_PTR); 226 } 227 } 228 229 SPAN_TEST(from_nullptr_length_constructor) { 230 { 231 Span<int> s{nullptr, static_cast<Span<int>::index_type>(0)}; 232 ASSERT_EQ(s.Length(), 0U); 233 ASSERT_EQ(s.data(), SLICE_INT_PTR); 234 235 Span<const int> cs{nullptr, static_cast<Span<int>::index_type>(0)}; 236 ASSERT_EQ(cs.Length(), 0U); 237 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR); 238 } 239 240 { 241 Span<int, 0> s{nullptr, static_cast<Span<int>::index_type>(0)}; 242 ASSERT_EQ(s.Length(), 0U); 243 ASSERT_EQ(s.data(), SLICE_INT_PTR); 244 245 Span<const int, 0> cs{nullptr, static_cast<Span<int>::index_type>(0)}; 246 ASSERT_EQ(cs.Length(), 0U); 247 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR); 248 } 249 250 #if 0 251 { 252 auto workaround_macro = []() { Span<int, 1> s{ nullptr, static_cast<Span<int>::index_type>(0) }; }; 253 CHECK_THROW(workaround_macro(), fail_fast); 254 } 255 256 { 257 auto workaround_macro = []() { Span<int> s{nullptr, 1}; }; 258 CHECK_THROW(workaround_macro(), fail_fast); 259 260 auto const_workaround_macro = []() { Span<const int> cs{nullptr, 1}; }; 261 CHECK_THROW(const_workaround_macro(), fail_fast); 262 } 263 264 { 265 auto workaround_macro = []() { Span<int, 0> s{nullptr, 1}; }; 266 CHECK_THROW(workaround_macro(), fail_fast); 267 268 auto const_workaround_macro = []() { Span<const int, 0> s{nullptr, 1}; }; 269 CHECK_THROW(const_workaround_macro(), fail_fast); 270 } 271 #endif 272 { 273 Span<int*> s{nullptr, static_cast<Span<int>::index_type>(0)}; 274 ASSERT_EQ(s.Length(), 0U); 275 ASSERT_EQ(s.data(), SLICE_INT_PTR_PTR); 276 277 Span<const int*> cs{nullptr, static_cast<Span<int>::index_type>(0)}; 278 ASSERT_EQ(cs.Length(), 0U); 279 ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR_PTR); 280 } 281 } 282 283 SPAN_TEST(from_pointer_length_constructor) { 284 int arr[4] = {1, 2, 3, 4}; 285 286 { 287 Span<int> s{&arr[0], 2}; 288 ASSERT_EQ(s.Length(), 2U); 289 ASSERT_EQ(s.data(), &arr[0]); 290 ASSERT_EQ(s[0], 1); 291 ASSERT_EQ(s[1], 2); 292 } 293 294 { 295 Span<int, 2> s{&arr[0], 2}; 296 ASSERT_EQ(s.Length(), 2U); 297 ASSERT_EQ(s.data(), &arr[0]); 298 ASSERT_EQ(s[0], 1); 299 ASSERT_EQ(s[1], 2); 300 } 301 302 { 303 int* p = nullptr; 304 Span<int> s{p, static_cast<Span<int>::index_type>(0)}; 305 ASSERT_EQ(s.Length(), 0U); 306 ASSERT_EQ(s.data(), SLICE_INT_PTR); 307 } 308 309 #if 0 310 { 311 int* p = nullptr; 312 auto workaround_macro = [=]() { Span<int> s{p, 2}; }; 313 CHECK_THROW(workaround_macro(), fail_fast); 314 } 315 #endif 316 317 { 318 auto s = Span(&arr[0], 2); 319 ASSERT_EQ(s.Length(), 2U); 320 ASSERT_EQ(s.data(), &arr[0]); 321 ASSERT_EQ(s[0], 1); 322 ASSERT_EQ(s[1], 2); 323 } 324 325 { 326 int* p = nullptr; 327 auto s = Span(p, static_cast<Span<int>::index_type>(0)); 328 ASSERT_EQ(s.Length(), 0U); 329 ASSERT_EQ(s.data(), SLICE_INT_PTR); 330 } 331 332 #if 0 333 { 334 int* p = nullptr; 335 auto workaround_macro = [=]() { Span(p, 2); }; 336 CHECK_THROW(workaround_macro(), fail_fast); 337 } 338 #endif 339 } 340 341 SPAN_TEST(from_pointer_pointer_constructor) { 342 int arr[4] = {1, 2, 3, 4}; 343 344 { 345 Span<int> s{&arr[0], &arr[2]}; 346 ASSERT_EQ(s.Length(), 2U); 347 ASSERT_EQ(s.data(), &arr[0]); 348 ASSERT_EQ(s[0], 1); 349 ASSERT_EQ(s[1], 2); 350 } 351 352 { 353 Span<int, 2> s{&arr[0], &arr[2]}; 354 ASSERT_EQ(s.Length(), 2U); 355 ASSERT_EQ(s.data(), &arr[0]); 356 ASSERT_EQ(s[0], 1); 357 ASSERT_EQ(s[1], 2); 358 } 359 360 { 361 Span<int> s{&arr[0], &arr[0]}; 362 ASSERT_EQ(s.Length(), 0U); 363 ASSERT_EQ(s.data(), &arr[0]); 364 } 365 366 { 367 Span<int, 0> s{&arr[0], &arr[0]}; 368 ASSERT_EQ(s.Length(), 0U); 369 ASSERT_EQ(s.data(), &arr[0]); 370 } 371 372 // this will fail the std::distance() precondition, which asserts on MSVC 373 // debug builds 374 //{ 375 // auto workaround_macro = [&]() { Span<int> s{&arr[1], &arr[0]}; }; 376 // CHECK_THROW(workaround_macro(), fail_fast); 377 //} 378 379 // this will fail the std::distance() precondition, which asserts on MSVC 380 // debug builds 381 //{ 382 // int* p = nullptr; 383 // auto workaround_macro = [&]() { Span<int> s{&arr[0], p}; }; 384 // CHECK_THROW(workaround_macro(), fail_fast); 385 //} 386 387 { 388 int* p = nullptr; 389 Span<int> s{p, p}; 390 ASSERT_EQ(s.Length(), 0U); 391 ASSERT_EQ(s.data(), SLICE_INT_PTR); 392 } 393 394 { 395 int* p = nullptr; 396 Span<int, 0> s{p, p}; 397 ASSERT_EQ(s.Length(), 0U); 398 ASSERT_EQ(s.data(), SLICE_INT_PTR); 399 } 400 401 // this will fail the std::distance() precondition, which asserts on MSVC 402 // debug builds 403 //{ 404 // int* p = nullptr; 405 // auto workaround_macro = [&]() { Span<int> s{&arr[0], p}; }; 406 // CHECK_THROW(workaround_macro(), fail_fast); 407 //} 408 409 { 410 auto s = Span(&arr[0], &arr[2]); 411 ASSERT_EQ(s.Length(), 2U); 412 ASSERT_EQ(s.data(), &arr[0]); 413 ASSERT_EQ(s[0], 1); 414 ASSERT_EQ(s[1], 2); 415 } 416 417 { 418 auto s = Span(&arr[0], &arr[0]); 419 ASSERT_EQ(s.Length(), 0U); 420 ASSERT_EQ(s.data(), &arr[0]); 421 } 422 423 { 424 int* p = nullptr; 425 auto s = Span(p, p); 426 ASSERT_EQ(s.Length(), 0U); 427 ASSERT_EQ(s.data(), SLICE_INT_PTR); 428 } 429 } 430 431 SPAN_TEST(from_array_constructor) { 432 int arr[5] = {1, 2, 3, 4, 5}; 433 434 { 435 Span<int> s{arr}; 436 ASSERT_EQ(s.Length(), 5U); 437 ASSERT_EQ(s.data(), &arr[0]); 438 } 439 440 { 441 Span<int, 5> s{arr}; 442 ASSERT_EQ(s.Length(), 5U); 443 ASSERT_EQ(s.data(), &arr[0]); 444 } 445 446 int arr2d[2][3] = {{1, 2, 3}, {4, 5, 6}}; 447 448 #ifdef CONFIRM_COMPILATION_ERRORS 449 { 450 Span<int, 6> s{arr}; 451 } 452 453 { 454 Span<int, 0> s{arr}; 455 ASSERT_EQ(s.Length(), 0U); 456 ASSERT_EQ(s.data(), &arr[0]); 457 } 458 459 { 460 Span<int> s{arr2d}; 461 ASSERT_EQ(s.Length(), 6U); 462 ASSERT_EQ(s.data(), &arr2d[0][0]); 463 ASSERT_EQ(s[0], 1); 464 ASSERT_EQ(s[5], 6); 465 } 466 467 { 468 Span<int, 0> s{arr2d}; 469 ASSERT_EQ(s.Length(), 0U); 470 ASSERT_EQ(s.data(), &arr2d[0][0]); 471 } 472 473 { 474 Span<int, 6> s{arr2d}; 475 } 476 #endif 477 { 478 Span<int[3]> s{&(arr2d[0]), 1}; 479 ASSERT_EQ(s.Length(), 1U); 480 ASSERT_EQ(s.data(), &arr2d[0]); 481 } 482 483 int arr3d[2][3][2] = {{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}}; 484 485 #ifdef CONFIRM_COMPILATION_ERRORS 486 { 487 Span<int> s{arr3d}; 488 ASSERT_EQ(s.Length(), 12U); 489 ASSERT_EQ(s.data(), &arr3d[0][0][0]); 490 ASSERT_EQ(s[0], 1); 491 ASSERT_EQ(s[11], 12); 492 } 493 494 { 495 Span<int, 0> s{arr3d}; 496 ASSERT_EQ(s.Length(), 0U); 497 ASSERT_EQ(s.data(), &arr3d[0][0][0]); 498 } 499 500 { 501 Span<int, 11> s{arr3d}; 502 } 503 504 { 505 Span<int, 12> s{arr3d}; 506 ASSERT_EQ(s.Length(), 12U); 507 ASSERT_EQ(s.data(), &arr3d[0][0][0]); 508 ASSERT_EQ(s[0], 1); 509 ASSERT_EQ(s[5], 6); 510 } 511 #endif 512 { 513 Span<int[3][2]> s{&arr3d[0], 1}; 514 ASSERT_EQ(s.Length(), 1U); 515 ASSERT_EQ(s.data(), &arr3d[0]); 516 } 517 518 { 519 auto s = Span(arr); 520 ASSERT_EQ(s.Length(), 5U); 521 ASSERT_EQ(s.data(), &arr[0]); 522 } 523 524 { 525 auto s = Span(&(arr2d[0]), 1); 526 ASSERT_EQ(s.Length(), 1U); 527 ASSERT_EQ(s.data(), &arr2d[0]); 528 } 529 530 { 531 auto s = Span(&arr3d[0], 1); 532 ASSERT_EQ(s.Length(), 1U); 533 ASSERT_EQ(s.data(), &arr3d[0]); 534 } 535 } 536 537 SPAN_TEST(from_dynamic_array_constructor) { 538 double(*arr)[3][4] = new double[100][3][4]; 539 540 { 541 Span<double> s(&arr[0][0][0], 10); 542 ASSERT_EQ(s.Length(), 10U); 543 ASSERT_EQ(s.data(), &arr[0][0][0]); 544 } 545 546 { 547 auto s = Span(&arr[0][0][0], 10); 548 ASSERT_EQ(s.Length(), 10U); 549 ASSERT_EQ(s.data(), &arr[0][0][0]); 550 } 551 552 delete[] arr; 553 } 554 555 SPAN_TEST(from_std_array_constructor) { 556 std::array<int, 4> arr = {{1, 2, 3, 4}}; 557 558 { 559 Span<int> s{arr}; 560 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 561 ASSERT_EQ(s.data(), arr.data()); 562 563 Span<const int> cs{arr}; 564 ASSERT_EQ(cs.size(), narrow_cast<size_t>(arr.size())); 565 ASSERT_EQ(cs.data(), arr.data()); 566 } 567 568 { 569 Span<int, 4> s{arr}; 570 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 571 ASSERT_EQ(s.data(), arr.data()); 572 573 Span<const int, 4> cs{arr}; 574 ASSERT_EQ(cs.size(), narrow_cast<size_t>(arr.size())); 575 ASSERT_EQ(cs.data(), arr.data()); 576 } 577 578 #ifdef CONFIRM_COMPILATION_ERRORS 579 { 580 Span<int, 2> s{arr}; 581 ASSERT_EQ(s.size(), 2U); 582 ASSERT_EQ(s.data(), arr.data()); 583 584 Span<const int, 2> cs{arr}; 585 ASSERT_EQ(cs.size(), 2U); 586 ASSERT_EQ(cs.data(), arr.data()); 587 } 588 589 { 590 Span<int, 0> s{arr}; 591 ASSERT_EQ(s.size(), 0U); 592 ASSERT_EQ(s.data(), arr.data()); 593 594 Span<const int, 0> cs{arr}; 595 ASSERT_EQ(cs.size(), 0U); 596 ASSERT_EQ(cs.data(), arr.data()); 597 } 598 599 { 600 Span<int, 5> s{arr}; 601 } 602 603 { 604 auto get_an_array = []() -> std::array<int, 4> { return {1, 2, 3, 4}; }; 605 auto take_a_Span = [](Span<int> s) { static_cast<void>(s); }; 606 // try to take a temporary std::array 607 take_a_Span(get_an_array()); 608 } 609 #endif 610 611 { 612 auto get_an_array = []() -> std::array<int, 4> { return {{1, 2, 3, 4}}; }; 613 auto take_a_Span = [](Span<const int> s) { static_cast<void>(s); }; 614 // try to take a temporary std::array 615 take_a_Span(get_an_array()); 616 } 617 618 { 619 auto s = Span(arr); 620 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 621 ASSERT_EQ(s.data(), arr.data()); 622 } 623 } 624 625 SPAN_TEST(from_const_std_array_constructor) { 626 const std::array<int, 4> arr = {{1, 2, 3, 4}}; 627 628 { 629 Span<const int> s{arr}; 630 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 631 ASSERT_EQ(s.data(), arr.data()); 632 } 633 634 { 635 Span<const int, 4> s{arr}; 636 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 637 ASSERT_EQ(s.data(), arr.data()); 638 } 639 640 #ifdef CONFIRM_COMPILATION_ERRORS 641 { 642 Span<const int, 2> s{arr}; 643 ASSERT_EQ(s.size(), 2U); 644 ASSERT_EQ(s.data(), arr.data()); 645 } 646 647 { 648 Span<const int, 0> s{arr}; 649 ASSERT_EQ(s.size(), 0U); 650 ASSERT_EQ(s.data(), arr.data()); 651 } 652 653 { 654 Span<const int, 5> s{arr}; 655 } 656 #endif 657 658 { 659 auto get_an_array = []() -> const std::array<int, 4> { 660 return {{1, 2, 3, 4}}; 661 }; 662 auto take_a_Span = [](Span<const int> s) { static_cast<void>(s); }; 663 // try to take a temporary std::array 664 take_a_Span(get_an_array()); 665 } 666 667 { 668 auto s = Span(arr); 669 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 670 ASSERT_EQ(s.data(), arr.data()); 671 } 672 } 673 674 SPAN_TEST(from_std_array_const_constructor) { 675 std::array<const int, 4> arr = {{1, 2, 3, 4}}; 676 677 { 678 Span<const int> s{arr}; 679 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 680 ASSERT_EQ(s.data(), arr.data()); 681 } 682 683 { 684 Span<const int, 4> s{arr}; 685 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 686 ASSERT_EQ(s.data(), arr.data()); 687 } 688 689 #ifdef CONFIRM_COMPILATION_ERRORS 690 { 691 Span<const int, 2> s{arr}; 692 ASSERT_EQ(s.size(), 2U); 693 ASSERT_EQ(s.data(), arr.data()); 694 } 695 696 { 697 Span<const int, 0> s{arr}; 698 ASSERT_EQ(s.size(), 0U); 699 ASSERT_EQ(s.data(), arr.data()); 700 } 701 702 { 703 Span<const int, 5> s{arr}; 704 } 705 706 { 707 Span<int, 4> s{arr}; 708 } 709 #endif 710 711 { 712 auto s = Span(arr); 713 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size())); 714 ASSERT_EQ(s.data(), arr.data()); 715 } 716 } 717 718 SPAN_TEST(from_mozilla_array_constructor) { 719 mozilla::Array<int, 4> arr(1, 2, 3, 4); 720 721 { 722 Span<int> s{arr}; 723 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 724 ASSERT_EQ(s.data(), &arr[0]); 725 726 Span<const int> cs{arr}; 727 ASSERT_EQ(cs.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 728 ASSERT_EQ(cs.data(), &arr[0]); 729 } 730 731 { 732 Span<int, 4> s{arr}; 733 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 734 ASSERT_EQ(s.data(), &arr[0]); 735 736 Span<const int, 4> cs{arr}; 737 ASSERT_EQ(cs.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 738 ASSERT_EQ(cs.data(), &arr[0]); 739 } 740 741 #ifdef CONFIRM_COMPILATION_ERRORS 742 { 743 Span<int, 2> s{arr}; 744 ASSERT_EQ(s.size(), 2U); 745 ASSERT_EQ(s.data(), &arr[0]); 746 747 Span<const int, 2> cs{arr}; 748 ASSERT_EQ(cs.size(), 2U); 749 ASSERT_EQ(cs.data(), &arr[0]); 750 } 751 752 { 753 Span<int, 0> s{arr}; 754 ASSERT_EQ(s.size(), 0U); 755 ASSERT_EQ(s.data(), &arr[0]); 756 757 Span<const int, 0> cs{arr}; 758 ASSERT_EQ(cs.size(), 0U); 759 ASSERT_EQ(cs.data(), &arr[0]); 760 } 761 762 { 763 Span<int, 5> s{arr}; 764 } 765 766 { 767 auto get_an_array = []() -> mozilla::Array<int, 4> { return {1, 2, 3, 4}; }; 768 auto take_a_Span = [](Span<int> s) { static_cast<void>(s); }; 769 // try to take a temporary mozilla::Array 770 take_a_Span(get_an_array()); 771 } 772 #endif 773 774 { 775 auto get_an_array = []() -> mozilla::Array<int, 4> { return {1, 2, 3, 4}; }; 776 auto take_a_Span = [](Span<const int> s) { static_cast<void>(s); }; 777 // try to take a temporary mozilla::Array 778 take_a_Span(get_an_array()); 779 } 780 781 { 782 auto s = Span(arr); 783 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 784 ASSERT_EQ(s.data(), &arr[0]); 785 } 786 } 787 788 SPAN_TEST(from_const_mozilla_array_constructor) { 789 const mozilla::Array<int, 4> arr(1, 2, 3, 4); 790 791 { 792 Span<const int> s{arr}; 793 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 794 ASSERT_EQ(s.data(), &arr[0]); 795 } 796 797 { 798 Span<const int, 4> s{arr}; 799 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 800 ASSERT_EQ(s.data(), &arr[0]); 801 } 802 803 #ifdef CONFIRM_COMPILATION_ERRORS 804 { 805 Span<const int, 2> s{arr}; 806 ASSERT_EQ(s.size(), 2U); 807 ASSERT_EQ(s.data(), &arr[0]); 808 } 809 810 { 811 Span<const int, 0> s{arr}; 812 ASSERT_EQ(s.size(), 0U); 813 ASSERT_EQ(s.data(), &arr[0]); 814 } 815 816 { 817 Span<const int, 5> s{arr}; 818 } 819 #endif 820 821 #if 0 822 { 823 auto get_an_array = []() -> const mozilla::Array<int, 4> { 824 return { 1, 2, 3, 4 }; 825 }; 826 auto take_a_Span = [](Span<const int> s) { static_cast<void>(s); }; 827 // try to take a temporary mozilla::Array 828 take_a_Span(get_an_array()); 829 } 830 #endif 831 832 { 833 auto s = Span(arr); 834 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 835 ASSERT_EQ(s.data(), &arr[0]); 836 } 837 } 838 839 SPAN_TEST(from_mozilla_array_const_constructor) { 840 mozilla::Array<const int, 4> arr(1, 2, 3, 4); 841 842 { 843 Span<const int> s{arr}; 844 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 845 ASSERT_EQ(s.data(), &arr[0]); 846 } 847 848 { 849 Span<const int, 4> s{arr}; 850 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 851 ASSERT_EQ(s.data(), &arr[0]); 852 } 853 854 #ifdef CONFIRM_COMPILATION_ERRORS 855 { 856 Span<const int, 2> s{arr}; 857 ASSERT_EQ(s.size(), 2U); 858 ASSERT_EQ(s.data(), &arr[0]); 859 } 860 861 { 862 Span<const int, 0> s{arr}; 863 ASSERT_EQ(s.size(), 0U); 864 ASSERT_EQ(s.data(), &arr[0]); 865 } 866 867 { 868 Span<const int, 5> s{arr}; 869 } 870 871 { 872 Span<int, 4> s{arr}; 873 } 874 #endif 875 876 { 877 auto s = Span(arr); 878 ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin())); 879 ASSERT_EQ(s.data(), &arr[0]); 880 } 881 } 882 883 SPAN_TEST(from_container_constructor) { 884 std::vector<int> v = {1, 2, 3}; 885 const std::vector<int> cv = v; 886 887 { 888 AssertSpanOfThreeInts(v); 889 890 Span<int> s{v}; 891 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.size())); 892 ASSERT_EQ(s.data(), v.data()); 893 894 Span<const int> cs{v}; 895 ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.size())); 896 ASSERT_EQ(cs.data(), v.data()); 897 } 898 899 std::string str = "hello"; 900 const std::string cstr = "hello"; 901 902 { 903 #ifdef CONFIRM_COMPILATION_ERRORS 904 Span<char> s{str}; 905 ASSERT_EQ(s.size(), narrow_cast<size_t>(str.size())); 906 ASSERT_EQ(s.data(), str.data()); 907 #endif 908 Span<const char> cs{str}; 909 ASSERT_EQ(cs.size(), narrow_cast<size_t>(str.size())); 910 ASSERT_EQ(cs.data(), str.data()); 911 } 912 913 { 914 #ifdef CONFIRM_COMPILATION_ERRORS 915 Span<char> s{cstr}; 916 #endif 917 Span<const char> cs{cstr}; 918 ASSERT_EQ(cs.size(), narrow_cast<size_t>(cstr.size())); 919 ASSERT_EQ(cs.data(), cstr.data()); 920 } 921 922 { 923 #ifdef CONFIRM_COMPILATION_ERRORS 924 auto get_temp_vector = []() -> std::vector<int> { return {}; }; 925 auto use_Span = [](Span<int> s) { static_cast<void>(s); }; 926 use_Span(get_temp_vector()); 927 #endif 928 } 929 930 { 931 auto get_temp_vector = []() -> std::vector<int> { return {}; }; 932 auto use_Span = [](Span<const int> s) { static_cast<void>(s); }; 933 use_Span(get_temp_vector()); 934 } 935 936 { 937 #ifdef CONFIRM_COMPILATION_ERRORS 938 auto get_temp_string = []() -> std::string { return {}; }; 939 auto use_Span = [](Span<char> s) { static_cast<void>(s); }; 940 use_Span(get_temp_string()); 941 #endif 942 } 943 944 { 945 auto get_temp_string = []() -> std::string { return {}; }; 946 auto use_Span = [](Span<const char> s) { static_cast<void>(s); }; 947 use_Span(get_temp_string()); 948 } 949 950 { 951 #ifdef CONFIRM_COMPILATION_ERRORS 952 auto get_temp_vector = []() -> const std::vector<int> { return {}; }; 953 auto use_Span = [](Span<const char> s) { static_cast<void>(s); }; 954 use_Span(get_temp_vector()); 955 #endif 956 } 957 958 { 959 auto get_temp_string = []() -> const std::string { return {}; }; 960 auto use_Span = [](Span<const char> s) { static_cast<void>(s); }; 961 use_Span(get_temp_string()); 962 } 963 964 { 965 #ifdef CONFIRM_COMPILATION_ERRORS 966 std::map<int, int> m; 967 Span<int> s{m}; 968 #endif 969 } 970 971 { 972 auto s = Span(v); 973 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.size())); 974 ASSERT_EQ(s.data(), v.data()); 975 976 auto cs = Span(cv); 977 ASSERT_EQ(cs.size(), narrow_cast<size_t>(cv.size())); 978 ASSERT_EQ(cs.data(), cv.data()); 979 } 980 } 981 982 SPAN_TEST(from_xpcom_collections) { 983 { 984 nsTArray<int> v; 985 v.AppendElement(1); 986 v.AppendElement(2); 987 v.AppendElement(3); 988 989 AssertSpanOfThreeInts(v); 990 991 Span<int> s{v}; 992 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length())); 993 ASSERT_EQ(s.data(), v.Elements()); 994 ASSERT_EQ(s[2], 3); 995 996 Span<const int> cs{v}; 997 ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.Length())); 998 ASSERT_EQ(cs.data(), v.Elements()); 999 ASSERT_EQ(cs[2], 3); 1000 } 1001 { 1002 nsTArray<int> v; 1003 v.AppendElement(1); 1004 v.AppendElement(2); 1005 v.AppendElement(3); 1006 1007 AssertSpanOfThreeInts(v); 1008 1009 auto s = Span(v); 1010 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length())); 1011 ASSERT_EQ(s.data(), v.Elements()); 1012 ASSERT_EQ(s[2], 3); 1013 } 1014 { 1015 AutoTArray<int, 5> v; 1016 v.AppendElement(1); 1017 v.AppendElement(2); 1018 v.AppendElement(3); 1019 1020 AssertSpanOfThreeInts(v); 1021 1022 Span<int> s{v}; 1023 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length())); 1024 ASSERT_EQ(s.data(), v.Elements()); 1025 ASSERT_EQ(s[2], 3); 1026 1027 Span<const int> cs{v}; 1028 ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.Length())); 1029 ASSERT_EQ(cs.data(), v.Elements()); 1030 ASSERT_EQ(cs[2], 3); 1031 } 1032 { 1033 AutoTArray<int, 5> v; 1034 v.AppendElement(1); 1035 v.AppendElement(2); 1036 v.AppendElement(3); 1037 1038 AssertSpanOfThreeInts(v); 1039 1040 auto s = Span(v); 1041 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length())); 1042 ASSERT_EQ(s.data(), v.Elements()); 1043 ASSERT_EQ(s[2], 3); 1044 } 1045 { 1046 FallibleTArray<int> v; 1047 *(v.AppendElement(fallible)) = 1; 1048 *(v.AppendElement(fallible)) = 2; 1049 *(v.AppendElement(fallible)) = 3; 1050 1051 AssertSpanOfThreeInts(v); 1052 1053 Span<int> s{v}; 1054 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length())); 1055 ASSERT_EQ(s.data(), v.Elements()); 1056 ASSERT_EQ(s[2], 3); 1057 1058 Span<const int> cs{v}; 1059 ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.Length())); 1060 ASSERT_EQ(cs.data(), v.Elements()); 1061 ASSERT_EQ(cs[2], 3); 1062 } 1063 { 1064 FallibleTArray<int> v; 1065 *(v.AppendElement(fallible)) = 1; 1066 *(v.AppendElement(fallible)) = 2; 1067 *(v.AppendElement(fallible)) = 3; 1068 1069 AssertSpanOfThreeInts(v); 1070 1071 auto s = Span(v); 1072 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length())); 1073 ASSERT_EQ(s.data(), v.Elements()); 1074 ASSERT_EQ(s[2], 3); 1075 } 1076 { 1077 nsAutoString str; 1078 str.AssignLiteral(u"abc"); 1079 1080 AssertSpanOfThreeChar16s(str); 1081 AssertSpanOfThreeChar16sViaString(str); 1082 1083 Span<char16_t> s{str.GetMutableData()}; 1084 ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length())); 1085 ASSERT_EQ(s.data(), str.BeginWriting()); 1086 ASSERT_EQ(s[2], 'c'); 1087 1088 Span<const char16_t> cs{str}; 1089 ASSERT_EQ(cs.size(), narrow_cast<size_t>(str.Length())); 1090 ASSERT_EQ(cs.data(), str.BeginReading()); 1091 ASSERT_EQ(cs[2], 'c'); 1092 } 1093 { 1094 nsAutoString str; 1095 str.AssignLiteral(u"abc"); 1096 1097 AssertSpanOfThreeChar16s(str); 1098 AssertSpanOfThreeChar16sViaString(str); 1099 1100 auto s = Span(str); 1101 ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length())); 1102 ASSERT_EQ(s.data(), str.BeginReading()); 1103 ASSERT_EQ(s[2], 'c'); 1104 } 1105 { 1106 nsAutoCString str; 1107 str.AssignLiteral("abc"); 1108 1109 AssertSpanOfThreeChars(str); 1110 AssertSpanOfThreeCharsViaString(str); 1111 1112 Span<const uint8_t> cs{str}; 1113 ASSERT_EQ(cs.size(), narrow_cast<size_t>(str.Length())); 1114 ASSERT_EQ(cs.data(), reinterpret_cast<const uint8_t*>(str.BeginReading())); 1115 ASSERT_EQ(cs[2], 'c'); 1116 } 1117 { 1118 nsAutoCString str; 1119 str.AssignLiteral("abc"); 1120 1121 AssertSpanOfThreeChars(str); 1122 AssertSpanOfThreeCharsViaString(str); 1123 1124 auto s = Span(str); 1125 ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length())); 1126 ASSERT_EQ(s.data(), str.BeginReading()); 1127 ASSERT_EQ(s[2], 'c'); 1128 } 1129 { 1130 nsTArray<int> v; 1131 v.AppendElement(1); 1132 v.AppendElement(2); 1133 v.AppendElement(3); 1134 1135 Range<int> r(v.Elements(), v.Length()); 1136 1137 AssertSpanOfThreeInts(r); 1138 1139 Span<int> s{r}; 1140 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length())); 1141 ASSERT_EQ(s.data(), v.Elements()); 1142 ASSERT_EQ(s[2], 3); 1143 1144 Span<const int> cs{r}; 1145 ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.Length())); 1146 ASSERT_EQ(cs.data(), v.Elements()); 1147 ASSERT_EQ(cs[2], 3); 1148 } 1149 { 1150 nsTArray<int> v; 1151 v.AppendElement(1); 1152 v.AppendElement(2); 1153 v.AppendElement(3); 1154 1155 Range<int> r(v.Elements(), v.Length()); 1156 1157 AssertSpanOfThreeInts(r); 1158 1159 auto s = Span(r); 1160 ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length())); 1161 ASSERT_EQ(s.data(), v.Elements()); 1162 ASSERT_EQ(s[2], 3); 1163 } 1164 } 1165 1166 SPAN_TEST(from_cstring) { 1167 { 1168 const char* str = nullptr; 1169 auto cs = MakeStringSpan(str); 1170 ASSERT_EQ(cs.size(), 0U); 1171 } 1172 { 1173 const char* str = "abc"; 1174 1175 auto cs = MakeStringSpan(str); 1176 ASSERT_EQ(cs.size(), 3U); 1177 ASSERT_EQ(cs.data(), str); 1178 ASSERT_EQ(cs[2], 'c'); 1179 1180 static_assert(MakeStringSpan("abc").size() == 3U); 1181 static_assert(MakeStringSpan("abc")[2] == 'c'); 1182 1183 #ifdef CONFIRM_COMPILATION_ERRORS 1184 Span<const char> scccl("literal"); // error 1185 1186 Span<const char> sccel; 1187 sccel = "literal"; // error 1188 1189 cs = Span("literal"); // error 1190 #endif 1191 } 1192 { 1193 char arr[4] = {'a', 'b', 'c', 0}; 1194 1195 auto cs = MakeStringSpan(arr); 1196 ASSERT_EQ(cs.size(), 3U); 1197 ASSERT_EQ(cs.data(), arr); 1198 ASSERT_EQ(cs[2], 'c'); 1199 1200 cs = Span(arr); 1201 ASSERT_EQ(cs.size(), 4U); // zero terminator is part of the array span. 1202 ASSERT_EQ(cs.data(), arr); 1203 ASSERT_EQ(cs[2], 'c'); 1204 ASSERT_EQ(cs[3], '\0'); // zero terminator is part of the array span. 1205 1206 #ifdef CONFIRM_COMPILATION_ERRORS 1207 Span<char> scca(arr); // error 1208 Span<const char> sccca(arr); // error 1209 1210 Span<const char> scccea; 1211 scccea = arr; // error 1212 #endif 1213 } 1214 { 1215 const char16_t* str = nullptr; 1216 auto cs = MakeStringSpan(str); 1217 ASSERT_EQ(cs.size(), 0U); 1218 } 1219 { 1220 char16_t arr[4] = {'a', 'b', 'c', 0}; 1221 const char16_t* str = arr; 1222 1223 auto cs = MakeStringSpan(str); 1224 ASSERT_EQ(cs.size(), 3U); 1225 ASSERT_EQ(cs.data(), str); 1226 ASSERT_EQ(cs[2], 'c'); 1227 1228 static_assert(MakeStringSpan(u"abc").size() == 3U); 1229 static_assert(MakeStringSpan(u"abc")[2] == u'c'); 1230 1231 cs = MakeStringSpan(arr); 1232 ASSERT_EQ(cs.size(), 3U); 1233 ASSERT_EQ(cs.data(), str); 1234 ASSERT_EQ(cs[2], 'c'); 1235 1236 cs = Span(arr); 1237 ASSERT_EQ(cs.size(), 4U); // zero terminator is part of the array span. 1238 ASSERT_EQ(cs.data(), str); 1239 ASSERT_EQ(cs[2], 'c'); 1240 ASSERT_EQ(cs[3], '\0'); // zero terminator is part of the array span. 1241 1242 #ifdef CONFIRM_COMPILATION_ERRORS 1243 Span<char16_t> scca(arr); // error 1244 1245 Span<const char16_t> scccea; 1246 scccea = arr; // error 1247 1248 Span<const char16_t> scccl(u"literal"); // error 1249 1250 Span<const char16_t>* sccel; 1251 *sccel = u"literal"; // error 1252 1253 cs = Span(u"literal"); // error 1254 #endif 1255 } 1256 } 1257 1258 SPAN_TEST(from_convertible_Span_constructor) { 1259 { 1260 Span<DerivedClass> avd; 1261 Span<const DerivedClass> avcd = avd; 1262 static_cast<void>(avcd); 1263 } 1264 1265 { 1266 #ifdef CONFIRM_COMPILATION_ERRORS 1267 Span<DerivedClass> avd; 1268 Span<BaseClass> avb = avd; 1269 static_cast<void>(avb); 1270 #endif 1271 } 1272 1273 #ifdef CONFIRM_COMPILATION_ERRORS 1274 { 1275 Span<int> s; 1276 Span<unsigned int> s2 = s; 1277 static_cast<void>(s2); 1278 } 1279 1280 { 1281 Span<int> s; 1282 Span<const unsigned int> s2 = s; 1283 static_cast<void>(s2); 1284 } 1285 1286 { 1287 Span<int> s; 1288 Span<short> s2 = s; 1289 static_cast<void>(s2); 1290 } 1291 #endif 1292 } 1293 1294 SPAN_TEST(copy_move_and_assignment) { 1295 Span<int> s1; 1296 ASSERT_TRUE(s1.empty()); 1297 1298 int arr[] = {3, 4, 5}; 1299 1300 Span<const int> s2 = arr; 1301 ASSERT_EQ(s2.Length(), 3U); 1302 ASSERT_EQ(s2.data(), &arr[0]); 1303 1304 s2 = s1; 1305 ASSERT_TRUE(s2.empty()); 1306 1307 auto get_temp_Span = [&]() -> Span<int> { return {&arr[1], 2}; }; 1308 auto use_Span = [&](Span<const int> s) { 1309 ASSERT_EQ(s.Length(), 2U); 1310 ASSERT_EQ(s.data(), &arr[1]); 1311 }; 1312 use_Span(get_temp_Span()); 1313 1314 s1 = get_temp_Span(); 1315 ASSERT_EQ(s1.Length(), 2U); 1316 ASSERT_EQ(s1.data(), &arr[1]); 1317 } 1318 1319 SPAN_TEST(first) { 1320 int arr[5] = {1, 2, 3, 4, 5}; 1321 1322 { 1323 Span<int, 5> av = arr; 1324 ASSERT_EQ(av.First<2>().Length(), 2U); 1325 ASSERT_EQ(av.First(2).Length(), 2U); 1326 } 1327 1328 { 1329 Span<int, 5> av = arr; 1330 ASSERT_EQ(av.First<0>().Length(), 0U); 1331 ASSERT_EQ(av.First(0).Length(), 0U); 1332 } 1333 1334 { 1335 Span<int, 5> av = arr; 1336 ASSERT_EQ(av.First<5>().Length(), 5U); 1337 ASSERT_EQ(av.First(5).Length(), 5U); 1338 } 1339 1340 #if 0 1341 { 1342 Span<int, 5> av = arr; 1343 # ifdef CONFIRM_COMPILATION_ERRORS 1344 ASSERT_EQ(av.First<6>().Length() , 6U); 1345 ASSERT_EQ(av.First<-1>().Length() , -1); 1346 # endif 1347 CHECK_THROW(av.First(6).Length(), fail_fast); 1348 } 1349 #endif 1350 1351 { 1352 Span<int> av; 1353 ASSERT_EQ(av.First<0>().Length(), 0U); 1354 ASSERT_EQ(av.First(0).Length(), 0U); 1355 } 1356 } 1357 1358 SPAN_TEST(last) { 1359 int arr[5] = {1, 2, 3, 4, 5}; 1360 1361 { 1362 Span<int, 5> av = arr; 1363 ASSERT_EQ(av.Last<2>().Length(), 2U); 1364 ASSERT_EQ(av.Last(2).Length(), 2U); 1365 } 1366 1367 { 1368 Span<int, 5> av = arr; 1369 ASSERT_EQ(av.Last<0>().Length(), 0U); 1370 ASSERT_EQ(av.Last(0).Length(), 0U); 1371 } 1372 1373 { 1374 Span<int, 5> av = arr; 1375 ASSERT_EQ(av.Last<5>().Length(), 5U); 1376 ASSERT_EQ(av.Last(5).Length(), 5U); 1377 } 1378 1379 #if 0 1380 { 1381 Span<int, 5> av = arr; 1382 # ifdef CONFIRM_COMPILATION_ERRORS 1383 ASSERT_EQ(av.Last<6>().Length() , 6U); 1384 # endif 1385 CHECK_THROW(av.Last(6).Length(), fail_fast); 1386 } 1387 #endif 1388 1389 { 1390 Span<int> av; 1391 ASSERT_EQ(av.Last<0>().Length(), 0U); 1392 ASSERT_EQ(av.Last(0).Length(), 0U); 1393 } 1394 } 1395 1396 SPAN_TEST(from_to) { 1397 int arr[5] = {1, 2, 3, 4, 5}; 1398 1399 { 1400 Span<int, 5> av = arr; 1401 ASSERT_EQ(av.From(3).Length(), 2U); 1402 ASSERT_EQ(av.From(2)[1], 4); 1403 } 1404 1405 { 1406 Span<int, 5> av = arr; 1407 ASSERT_EQ(av.From(5).Length(), 0U); 1408 } 1409 1410 { 1411 Span<int, 5> av = arr; 1412 ASSERT_EQ(av.From(0).Length(), 5U); 1413 } 1414 1415 { 1416 Span<int, 5> av = arr; 1417 ASSERT_EQ(av.To(3).Length(), 3U); 1418 ASSERT_EQ(av.To(3)[1], 2); 1419 } 1420 1421 { 1422 Span<int, 5> av = arr; 1423 ASSERT_EQ(av.To(0).Length(), 0U); 1424 } 1425 1426 { 1427 Span<int, 5> av = arr; 1428 ASSERT_EQ(av.To(5).Length(), 5U); 1429 } 1430 1431 { 1432 Span<int, 5> av = arr; 1433 ASSERT_EQ(av.FromTo(1, 4).Length(), 3U); 1434 ASSERT_EQ(av.FromTo(1, 4)[1], 3); 1435 } 1436 1437 { 1438 Span<int, 5> av = arr; 1439 ASSERT_EQ(av.FromTo(2, 2).Length(), 0U); 1440 } 1441 1442 { 1443 Span<int, 5> av = arr; 1444 ASSERT_EQ(av.FromTo(0, 5).Length(), 5U); 1445 } 1446 } 1447 1448 SPAN_TEST(Subspan) { 1449 int arr[5] = {1, 2, 3, 4, 5}; 1450 1451 { 1452 Span<int, 5> av = arr; 1453 ASSERT_EQ((av.Subspan<2, 2>().Length()), 2U); 1454 ASSERT_EQ(av.Subspan(2, 2).Length(), 2U); 1455 ASSERT_EQ(av.Subspan(2, 3).Length(), 3U); 1456 } 1457 1458 { 1459 Span<int, 5> av = arr; 1460 ASSERT_EQ((av.Subspan<0, 0>().Length()), 0U); 1461 ASSERT_EQ(av.Subspan(0, 0).Length(), 0U); 1462 } 1463 1464 { 1465 Span<int, 5> av = arr; 1466 ASSERT_EQ((av.Subspan<0, 5>().Length()), 5U); 1467 ASSERT_EQ(av.Subspan(0, 5).Length(), 5U); 1468 CHECK_THROW(av.Subspan(0, 6).Length(), fail_fast); 1469 CHECK_THROW(av.Subspan(1, 5).Length(), fail_fast); 1470 } 1471 1472 { 1473 Span<int, 5> av = arr; 1474 ASSERT_EQ((av.Subspan<4, 0>().Length()), 0U); 1475 ASSERT_EQ(av.Subspan(4, 0).Length(), 0U); 1476 ASSERT_EQ(av.Subspan(5, 0).Length(), 0U); 1477 CHECK_THROW(av.Subspan(6, 0).Length(), fail_fast); 1478 } 1479 1480 { 1481 Span<int> av; 1482 ASSERT_EQ((av.Subspan<0, 0>().Length()), 0U); 1483 ASSERT_EQ(av.Subspan(0, 0).Length(), 0U); 1484 CHECK_THROW((av.Subspan<1, 0>().Length()), fail_fast); 1485 } 1486 1487 { 1488 Span<int> av; 1489 ASSERT_EQ(av.Subspan(0).Length(), 0U); 1490 CHECK_THROW(av.Subspan(1).Length(), fail_fast); 1491 } 1492 1493 { 1494 Span<int> av = arr; 1495 ASSERT_EQ(av.Subspan(0).Length(), 5U); 1496 ASSERT_EQ(av.Subspan(1).Length(), 4U); 1497 ASSERT_EQ(av.Subspan(4).Length(), 1U); 1498 ASSERT_EQ(av.Subspan(5).Length(), 0U); 1499 CHECK_THROW(av.Subspan(6).Length(), fail_fast); 1500 auto av2 = av.Subspan(1); 1501 for (int i = 0; i < 4; ++i) ASSERT_EQ(av2[i], i + 2); 1502 } 1503 1504 { 1505 Span<int, 5> av = arr; 1506 ASSERT_EQ(av.Subspan(0).Length(), 5U); 1507 ASSERT_EQ(av.Subspan(1).Length(), 4U); 1508 ASSERT_EQ(av.Subspan(4).Length(), 1U); 1509 ASSERT_EQ(av.Subspan(5).Length(), 0U); 1510 CHECK_THROW(av.Subspan(6).Length(), fail_fast); 1511 auto av2 = av.Subspan(1); 1512 for (int i = 0; i < 4; ++i) ASSERT_EQ(av2[i], i + 2); 1513 } 1514 } 1515 1516 SPAN_TEST(at_call) { 1517 int arr[4] = {1, 2, 3, 4}; 1518 1519 { 1520 Span<int> s = arr; 1521 ASSERT_EQ(s.at(0), 1); 1522 CHECK_THROW(s.at(5), fail_fast); 1523 } 1524 1525 { 1526 int arr2d[2] = {1, 6}; 1527 Span<int, 2> s = arr2d; 1528 ASSERT_EQ(s.at(0), 1); 1529 ASSERT_EQ(s.at(1), 6); 1530 CHECK_THROW(s.at(2), fail_fast); 1531 } 1532 } 1533 1534 SPAN_TEST(operator_function_call) { 1535 int arr[4] = {1, 2, 3, 4}; 1536 1537 { 1538 Span<int> s = arr; 1539 ASSERT_EQ(s(0), 1); 1540 CHECK_THROW(s(5), fail_fast); 1541 } 1542 1543 { 1544 int arr2d[2] = {1, 6}; 1545 Span<int, 2> s = arr2d; 1546 ASSERT_EQ(s(0), 1); 1547 ASSERT_EQ(s(1), 6); 1548 CHECK_THROW(s(2), fail_fast); 1549 } 1550 } 1551 1552 SPAN_TEST(iterator_default_init) { 1553 Span<int>::iterator it1; 1554 Span<int>::iterator it2; 1555 ASSERT_EQ(it1, it2); 1556 } 1557 1558 SPAN_TEST(const_iterator_default_init) { 1559 Span<int>::const_iterator it1; 1560 Span<int>::const_iterator it2; 1561 ASSERT_EQ(it1, it2); 1562 } 1563 1564 SPAN_TEST(iterator_conversions) { 1565 Span<int>::iterator badIt; 1566 Span<int>::const_iterator badConstIt; 1567 ASSERT_EQ(badIt, badConstIt); 1568 1569 int a[] = {1, 2, 3, 4}; 1570 Span<int> s = a; 1571 1572 auto it = s.begin(); 1573 auto cit = s.cbegin(); 1574 1575 ASSERT_EQ(it, cit); 1576 ASSERT_EQ(cit, it); 1577 1578 Span<int>::const_iterator cit2 = it; 1579 ASSERT_EQ(cit2, cit); 1580 1581 Span<int>::const_iterator cit3 = it + 4; 1582 ASSERT_EQ(cit3, s.cend()); 1583 } 1584 1585 SPAN_TEST(iterator_comparisons) { 1586 int a[] = {1, 2, 3, 4}; 1587 { 1588 Span<int> s = a; 1589 Span<int>::iterator it = s.begin(); 1590 auto it2 = it + 1; 1591 Span<int>::const_iterator cit = s.cbegin(); 1592 1593 ASSERT_EQ(it, cit); 1594 ASSERT_EQ(cit, it); 1595 ASSERT_EQ(it, it); 1596 ASSERT_EQ(cit, cit); 1597 ASSERT_EQ(cit, s.begin()); 1598 ASSERT_EQ(s.begin(), cit); 1599 ASSERT_EQ(s.cbegin(), cit); 1600 ASSERT_EQ(it, s.begin()); 1601 ASSERT_EQ(s.begin(), it); 1602 1603 ASSERT_NE(it, it2); 1604 ASSERT_NE(it2, it); 1605 ASSERT_NE(it, s.end()); 1606 ASSERT_NE(it2, s.end()); 1607 ASSERT_NE(s.end(), it); 1608 ASSERT_NE(it2, cit); 1609 ASSERT_NE(cit, it2); 1610 1611 ASSERT_LT(it, it2); 1612 ASSERT_LE(it, it2); 1613 ASSERT_LE(it2, s.end()); 1614 ASSERT_LT(it, s.end()); 1615 ASSERT_LE(it, cit); 1616 ASSERT_LE(cit, it); 1617 ASSERT_LT(cit, it2); 1618 ASSERT_LE(cit, it2); 1619 ASSERT_LT(cit, s.end()); 1620 ASSERT_LE(cit, s.end()); 1621 1622 ASSERT_GT(it2, it); 1623 ASSERT_GE(it2, it); 1624 ASSERT_GT(s.end(), it2); 1625 ASSERT_GE(s.end(), it2); 1626 ASSERT_GT(it2, cit); 1627 ASSERT_GE(it2, cit); 1628 } 1629 } 1630 1631 SPAN_TEST(begin_end) { 1632 { 1633 int a[] = {1, 2, 3, 4}; 1634 Span<int> s = a; 1635 1636 Span<int>::iterator it = s.begin(); 1637 Span<int>::iterator it2 = std::begin(s); 1638 ASSERT_EQ(it, it2); 1639 1640 it = s.end(); 1641 it2 = std::end(s); 1642 ASSERT_EQ(it, it2); 1643 } 1644 1645 { 1646 int a[] = {1, 2, 3, 4}; 1647 Span<int> s = a; 1648 1649 auto it = s.begin(); 1650 auto first = it; 1651 ASSERT_EQ(it, first); 1652 ASSERT_EQ(*it, 1); 1653 1654 auto beyond = s.end(); 1655 ASSERT_NE(it, beyond); 1656 CHECK_THROW(*beyond, fail_fast); 1657 1658 ASSERT_EQ(beyond - first, 4); 1659 ASSERT_EQ(first - first, 0); 1660 ASSERT_EQ(beyond - beyond, 0); 1661 1662 ++it; 1663 ASSERT_EQ(it - first, 1); 1664 ASSERT_EQ(*it, 2); 1665 *it = 22; 1666 ASSERT_EQ(*it, 22); 1667 ASSERT_EQ(beyond - it, 3); 1668 1669 it = first; 1670 ASSERT_EQ(it, first); 1671 while (it != s.end()) { 1672 *it = 5; 1673 ++it; 1674 } 1675 1676 ASSERT_EQ(it, beyond); 1677 ASSERT_EQ(it - beyond, 0); 1678 1679 for (auto& n : s) { 1680 ASSERT_EQ(n, 5); 1681 } 1682 } 1683 } 1684 1685 SPAN_TEST(cbegin_cend) { 1686 #if 0 1687 { 1688 int a[] = { 1, 2, 3, 4 }; 1689 Span<int> s = a; 1690 1691 Span<int>::const_iterator cit = s.cbegin(); 1692 Span<int>::const_iterator cit2 = std::cbegin(s); 1693 ASSERT_EQ(cit , cit2); 1694 1695 cit = s.cend(); 1696 cit2 = std::cend(s); 1697 ASSERT_EQ(cit , cit2); 1698 } 1699 #endif 1700 { 1701 int a[] = {1, 2, 3, 4}; 1702 Span<int> s = a; 1703 1704 auto it = s.cbegin(); 1705 auto first = it; 1706 ASSERT_EQ(it, first); 1707 ASSERT_EQ(*it, 1); 1708 1709 auto beyond = s.cend(); 1710 ASSERT_NE(it, beyond); 1711 CHECK_THROW(*beyond, fail_fast); 1712 1713 ASSERT_EQ(beyond - first, 4); 1714 ASSERT_EQ(first - first, 0); 1715 ASSERT_EQ(beyond - beyond, 0); 1716 1717 ++it; 1718 ASSERT_EQ(it - first, 1); 1719 ASSERT_EQ(*it, 2); 1720 ASSERT_EQ(beyond - it, 3); 1721 1722 int last = 0; 1723 it = first; 1724 ASSERT_EQ(it, first); 1725 while (it != s.cend()) { 1726 ASSERT_EQ(*it, last + 1); 1727 1728 last = *it; 1729 ++it; 1730 } 1731 1732 ASSERT_EQ(it, beyond); 1733 ASSERT_EQ(it - beyond, 0); 1734 } 1735 } 1736 1737 SPAN_TEST(rbegin_rend) { 1738 { 1739 int a[] = {1, 2, 3, 4}; 1740 Span<int> s = a; 1741 1742 auto it = s.rbegin(); 1743 auto first = it; 1744 ASSERT_EQ(it, first); 1745 ASSERT_EQ(*it, 4); 1746 1747 auto beyond = s.rend(); 1748 ASSERT_NE(it, beyond); 1749 CHECK_THROW(*beyond, fail_fast); 1750 1751 ASSERT_EQ(beyond - first, 4); 1752 ASSERT_EQ(first - first, 0); 1753 ASSERT_EQ(beyond - beyond, 0); 1754 1755 ++it; 1756 ASSERT_EQ(it - first, 1); 1757 ASSERT_EQ(*it, 3); 1758 *it = 22; 1759 ASSERT_EQ(*it, 22); 1760 ASSERT_EQ(beyond - it, 3); 1761 1762 it = first; 1763 ASSERT_EQ(it, first); 1764 while (it != s.rend()) { 1765 *it = 5; 1766 ++it; 1767 } 1768 1769 ASSERT_EQ(it, beyond); 1770 ASSERT_EQ(it - beyond, 0); 1771 1772 for (auto& n : s) { 1773 ASSERT_EQ(n, 5); 1774 } 1775 } 1776 } 1777 1778 SPAN_TEST(crbegin_crend) { 1779 { 1780 int a[] = {1, 2, 3, 4}; 1781 Span<int> s = a; 1782 1783 auto it = s.crbegin(); 1784 auto first = it; 1785 ASSERT_EQ(it, first); 1786 ASSERT_EQ(*it, 4); 1787 1788 auto beyond = s.crend(); 1789 ASSERT_NE(it, beyond); 1790 CHECK_THROW(*beyond, fail_fast); 1791 1792 ASSERT_EQ(beyond - first, 4); 1793 ASSERT_EQ(first - first, 0); 1794 ASSERT_EQ(beyond - beyond, 0); 1795 1796 ++it; 1797 ASSERT_EQ(it - first, 1); 1798 ASSERT_EQ(*it, 3); 1799 ASSERT_EQ(beyond - it, 3); 1800 1801 it = first; 1802 ASSERT_EQ(it, first); 1803 int last = 5; 1804 while (it != s.crend()) { 1805 ASSERT_EQ(*it, last - 1); 1806 last = *it; 1807 1808 ++it; 1809 } 1810 1811 ASSERT_EQ(it, beyond); 1812 ASSERT_EQ(it - beyond, 0); 1813 } 1814 } 1815 1816 SPAN_TEST(comparison_operators) { 1817 { 1818 Span<int> s1 = nullptr; 1819 Span<int> s2 = nullptr; 1820 ASSERT_EQ(s1, s2); 1821 ASSERT_FALSE(s1 != s2); 1822 ASSERT_FALSE(s1 < s2); 1823 ASSERT_LE(s1, s2); 1824 ASSERT_FALSE(s1 > s2); 1825 ASSERT_GE(s1, s2); 1826 ASSERT_EQ(s2, s1); 1827 ASSERT_FALSE(s2 != s1); 1828 ASSERT_FALSE(s2 < s1); 1829 ASSERT_LE(s2, s1); 1830 ASSERT_FALSE(s2 > s1); 1831 ASSERT_GE(s2, s1); 1832 } 1833 1834 { 1835 int arr[] = {2, 1}; 1836 Span<int> s1 = arr; 1837 Span<int> s2 = arr; 1838 1839 ASSERT_EQ(s1, s2); 1840 ASSERT_FALSE(s1 != s2); 1841 ASSERT_FALSE(s1 < s2); 1842 ASSERT_LE(s1, s2); 1843 ASSERT_FALSE(s1 > s2); 1844 ASSERT_GE(s1, s2); 1845 ASSERT_EQ(s2, s1); 1846 ASSERT_FALSE(s2 != s1); 1847 ASSERT_FALSE(s2 < s1); 1848 ASSERT_LE(s2, s1); 1849 ASSERT_FALSE(s2 > s1); 1850 ASSERT_GE(s2, s1); 1851 } 1852 1853 { 1854 int arr[] = {2, 1}; // bigger 1855 1856 Span<int> s1 = nullptr; 1857 Span<int> s2 = arr; 1858 1859 ASSERT_NE(s1, s2); 1860 ASSERT_NE(s2, s1); 1861 ASSERT_NE(s1, s2); 1862 ASSERT_NE(s2, s1); 1863 ASSERT_LT(s1, s2); 1864 ASSERT_FALSE(s2 < s1); 1865 ASSERT_LE(s1, s2); 1866 ASSERT_FALSE(s2 <= s1); 1867 ASSERT_GT(s2, s1); 1868 ASSERT_FALSE(s1 > s2); 1869 ASSERT_GE(s2, s1); 1870 ASSERT_FALSE(s1 >= s2); 1871 } 1872 1873 { 1874 int arr1[] = {1, 2}; 1875 int arr2[] = {1, 2}; 1876 Span<int> s1 = arr1; 1877 Span<int> s2 = arr2; 1878 1879 ASSERT_EQ(s1, s2); 1880 ASSERT_FALSE(s1 != s2); 1881 ASSERT_FALSE(s1 < s2); 1882 ASSERT_LE(s1, s2); 1883 ASSERT_FALSE(s1 > s2); 1884 ASSERT_GE(s1, s2); 1885 ASSERT_EQ(s2, s1); 1886 ASSERT_FALSE(s2 != s1); 1887 ASSERT_FALSE(s2 < s1); 1888 ASSERT_LE(s2, s1); 1889 ASSERT_FALSE(s2 > s1); 1890 ASSERT_GE(s2, s1); 1891 } 1892 1893 { 1894 int arr[] = {1, 2, 3}; 1895 1896 AssertSpanOfThreeInts(arr); 1897 1898 Span<int> s1 = {&arr[0], 2}; // shorter 1899 Span<int> s2 = arr; // longer 1900 1901 ASSERT_NE(s1, s2); 1902 ASSERT_NE(s2, s1); 1903 ASSERT_NE(s1, s2); 1904 ASSERT_NE(s2, s1); 1905 ASSERT_LT(s1, s2); 1906 ASSERT_FALSE(s2 < s1); 1907 ASSERT_LE(s1, s2); 1908 ASSERT_FALSE(s2 <= s1); 1909 ASSERT_GT(s2, s1); 1910 ASSERT_FALSE(s1 > s2); 1911 ASSERT_GE(s2, s1); 1912 ASSERT_FALSE(s1 >= s2); 1913 } 1914 1915 { 1916 int arr1[] = {1, 2}; // smaller 1917 int arr2[] = {2, 1}; // bigger 1918 1919 Span<int> s1 = arr1; 1920 Span<int> s2 = arr2; 1921 1922 ASSERT_NE(s1, s2); 1923 ASSERT_NE(s2, s1); 1924 ASSERT_NE(s1, s2); 1925 ASSERT_NE(s2, s1); 1926 ASSERT_LT(s1, s2); 1927 ASSERT_FALSE(s2 < s1); 1928 ASSERT_LE(s1, s2); 1929 ASSERT_FALSE(s2 <= s1); 1930 ASSERT_GT(s2, s1); 1931 ASSERT_FALSE(s1 > s2); 1932 ASSERT_GE(s2, s1); 1933 ASSERT_FALSE(s1 >= s2); 1934 } 1935 } 1936 1937 SPAN_TEST(as_bytes) { 1938 int a[] = {1, 2, 3, 4}; 1939 1940 { 1941 Span<const int> s = a; 1942 ASSERT_EQ(s.Length(), 4U); 1943 Span<const uint8_t> bs = AsBytes(s); 1944 ASSERT_EQ(static_cast<const void*>(bs.data()), 1945 static_cast<const void*>(s.data())); 1946 ASSERT_EQ(bs.Length(), s.LengthBytes()); 1947 } 1948 1949 { 1950 Span<int> s; 1951 auto bs = AsBytes(s); 1952 ASSERT_EQ(bs.Length(), s.Length()); 1953 ASSERT_EQ(bs.Length(), 0U); 1954 ASSERT_EQ(bs.size_bytes(), 0U); 1955 ASSERT_EQ(static_cast<const void*>(bs.data()), 1956 static_cast<const void*>(s.data())); 1957 ASSERT_EQ(bs.data(), reinterpret_cast<const uint8_t*>(SLICE_INT_PTR)); 1958 } 1959 1960 { 1961 Span<int> s = a; 1962 auto bs = AsBytes(s); 1963 ASSERT_EQ(static_cast<const void*>(bs.data()), 1964 static_cast<const void*>(s.data())); 1965 ASSERT_EQ(bs.Length(), s.LengthBytes()); 1966 } 1967 } 1968 1969 SPAN_TEST(as_writable_bytes) { 1970 int a[] = {1, 2, 3, 4}; 1971 1972 { 1973 #ifdef CONFIRM_COMPILATION_ERRORS 1974 // you should not be able to get writeable bytes for const objects 1975 Span<const int> s = a; 1976 ASSERT_EQ(s.Length(), 4U); 1977 Span<const byte> bs = AsWritableBytes(s); 1978 ASSERT_EQ(static_cast<void*>(bs.data()), static_cast<void*>(s.data())); 1979 ASSERT_EQ(bs.Length(), s.LengthBytes()); 1980 #endif 1981 } 1982 1983 { 1984 Span<int> s; 1985 auto bs = AsWritableBytes(s); 1986 ASSERT_EQ(bs.Length(), s.Length()); 1987 ASSERT_EQ(bs.Length(), 0U); 1988 ASSERT_EQ(bs.size_bytes(), 0U); 1989 ASSERT_EQ(static_cast<void*>(bs.data()), static_cast<void*>(s.data())); 1990 ASSERT_EQ(bs.data(), reinterpret_cast<uint8_t*>(SLICE_INT_PTR)); 1991 } 1992 1993 { 1994 Span<int> s = a; 1995 auto bs = AsWritableBytes(s); 1996 ASSERT_EQ(static_cast<void*>(bs.data()), static_cast<void*>(s.data())); 1997 ASSERT_EQ(bs.Length(), s.LengthBytes()); 1998 } 1999 } 2000 2001 SPAN_TEST(as_chars) { 2002 const uint8_t a[] = {1, 2, 3, 4}; 2003 Span<const uint8_t> u = Span(a); 2004 Span<const char> c = AsChars(u); 2005 ASSERT_EQ(static_cast<const void*>(u.data()), 2006 static_cast<const void*>(c.data())); 2007 ASSERT_EQ(u.size(), c.size()); 2008 } 2009 2010 SPAN_TEST(as_writable_chars) { 2011 uint8_t a[] = {1, 2, 3, 4}; 2012 Span<uint8_t> u = Span(a); 2013 Span<char> c = AsWritableChars(u); 2014 ASSERT_EQ(static_cast<void*>(u.data()), static_cast<void*>(c.data())); 2015 ASSERT_EQ(u.size(), c.size()); 2016 } 2017 2018 SPAN_TEST(fixed_size_conversions) { 2019 int arr[] = {1, 2, 3, 4}; 2020 2021 // converting to an Span from an equal size array is ok 2022 Span<int, 4> s4 = arr; 2023 ASSERT_EQ(s4.Length(), 4U); 2024 2025 // converting to dynamic_range is always ok 2026 { 2027 Span<int> s = s4; 2028 ASSERT_EQ(s.Length(), s4.Length()); 2029 static_cast<void>(s); 2030 } 2031 2032 // initialization or assignment to static Span that REDUCES size is NOT ok 2033 #ifdef CONFIRM_COMPILATION_ERRORS 2034 { 2035 Span<int, 2> s = arr; 2036 } 2037 { 2038 Span<int, 2> s2 = s4; 2039 static_cast<void>(s2); 2040 } 2041 #endif 2042 2043 #if 0 2044 // even when done dynamically 2045 { 2046 Span<int> s = arr; 2047 auto f = [&]() { 2048 Span<int, 2> s2 = s; 2049 static_cast<void>(s2); 2050 }; 2051 CHECK_THROW(f(), fail_fast); 2052 } 2053 #endif 2054 2055 // but doing so explicitly is ok 2056 2057 // you can convert statically 2058 { 2059 Span<int, 2> s2 = {arr, 2}; 2060 static_cast<void>(s2); 2061 } 2062 { 2063 Span<int, 1> s1 = s4.First<1>(); 2064 static_cast<void>(s1); 2065 } 2066 2067 // ...or dynamically 2068 { 2069 // NB: implicit conversion to Span<int,1> from Span<int> 2070 Span<int, 1> s1 = s4.First(1); 2071 static_cast<void>(s1); 2072 } 2073 2074 #if 0 2075 // initialization or assignment to static Span that requires size INCREASE is not ok. 2076 int arr2[2] = {1, 2}; 2077 #endif 2078 2079 #ifdef CONFIRM_COMPILATION_ERRORS 2080 { 2081 Span<int, 4> s3 = arr2; 2082 } 2083 { 2084 Span<int, 2> s2 = arr2; 2085 Span<int, 4> s4a = s2; 2086 } 2087 #endif 2088 2089 #if 0 2090 { 2091 auto f = [&]() { 2092 Span<int, 4> _s4 = {arr2, 2}; 2093 static_cast<void>(_s4); 2094 }; 2095 CHECK_THROW(f(), fail_fast); 2096 } 2097 2098 // this should fail - we are trying to assign a small dynamic Span to a fixed_size larger one 2099 Span<int> av = arr2; 2100 auto f = [&]() { 2101 Span<int, 4> _s4 = av; 2102 static_cast<void>(_s4); 2103 }; 2104 CHECK_THROW(f(), fail_fast); 2105 #endif 2106 } 2107 2108 #if 0 2109 SPAN_TEST(interop_with_std_regex) 2110 { 2111 char lat[] = { '1', '2', '3', '4', '5', '6', 'E', 'F', 'G' }; 2112 Span<char> s = lat; 2113 auto f_it = s.begin() + 7; 2114 2115 std::match_results<Span<char>::iterator> match; 2116 2117 std::regex_match(s.begin(), s.end(), match, std::regex(".*")); 2118 ASSERT_EQ(match.ready()); 2119 ASSERT_TRUE(!match.empty()); 2120 ASSERT_TRUE(match[0].matched); 2121 ASSERT_TRUE(match[0].first , s.begin()); 2122 ASSERT_EQ(match[0].second , s.end()); 2123 2124 std::regex_search(s.begin(), s.end(), match, std::regex("F")); 2125 ASSERT_TRUE(match.ready()); 2126 ASSERT_TRUE(!match.empty()); 2127 ASSERT_TRUE(match[0].matched); 2128 ASSERT_EQ(match[0].first , f_it); 2129 ASSERT_EQ(match[0].second , (f_it + 1)); 2130 } 2131 2132 SPAN_TEST(interop_with_gsl_at) 2133 { 2134 int arr[5] = { 1, 2, 3, 4, 5 }; 2135 Span<int> s{ arr }; 2136 ASSERT_EQ(at(s, 0) , 1 ); 2137 ASSERT_EQ(at(s, 1) , 2U); 2138 } 2139 #endif 2140 2141 SPAN_TEST(default_constructible) { 2142 ASSERT_TRUE((std::is_default_constructible<Span<int>>::value)); 2143 ASSERT_TRUE((std::is_default_constructible<Span<int, 0>>::value)); 2144 ASSERT_TRUE((!std::is_default_constructible<Span<int, 42>>::value)); 2145 } 2146 2147 SPAN_TEST(type_inference) { 2148 static constexpr int arr[5] = {1, 2, 3, 4, 5}; 2149 constexpr auto s = Span{arr}; 2150 static_assert(std::is_same_v<const Span<const int, 5>, decltype(s)>); 2151 static_assert(arr == s.Elements()); 2152 } 2153 2154 SPAN_TEST(split_at_dynamic_with_dynamic_extent) { 2155 static constexpr int arr[5] = {1, 2, 3, 4, 5}; 2156 constexpr Span<const int> s = Span{arr}; 2157 2158 { // Split at begin. 2159 constexpr auto splitAt0Result = s.SplitAt(0); 2160 static_assert( 2161 std::is_same_v<Span<const int>, decltype(splitAt0Result.first)>); 2162 static_assert( 2163 std::is_same_v<Span<const int>, decltype(splitAt0Result.second)>); 2164 ASSERT_EQ(s.Elements(), splitAt0Result.second.Elements()); 2165 ASSERT_EQ(0u, splitAt0Result.first.Length()); 2166 ASSERT_EQ(5u, splitAt0Result.second.Length()); 2167 } 2168 2169 { // Split at end. 2170 constexpr auto splitAt5Result = s.SplitAt(s.Length()); 2171 static_assert( 2172 std::is_same_v<Span<const int>, decltype(splitAt5Result.first)>); 2173 static_assert( 2174 std::is_same_v<Span<const int>, decltype(splitAt5Result.second)>); 2175 ASSERT_EQ(s.Elements(), splitAt5Result.first.Elements()); 2176 ASSERT_EQ(5u, splitAt5Result.first.Length()); 2177 ASSERT_EQ(0u, splitAt5Result.second.Length()); 2178 } 2179 2180 { 2181 // Split inside. 2182 constexpr auto splitAt3Result = s.SplitAt(3); 2183 static_assert( 2184 std::is_same_v<Span<const int>, decltype(splitAt3Result.first)>); 2185 static_assert( 2186 std::is_same_v<Span<const int>, decltype(splitAt3Result.second)>); 2187 ASSERT_EQ(s.Elements(), splitAt3Result.first.Elements()); 2188 ASSERT_EQ(s.Elements() + 3, splitAt3Result.second.Elements()); 2189 ASSERT_EQ(3u, splitAt3Result.first.Length()); 2190 ASSERT_EQ(2u, splitAt3Result.second.Length()); 2191 } 2192 } 2193 2194 SPAN_TEST(split_at_dynamic_with_static_extent) { 2195 static constexpr int arr[5] = {1, 2, 3, 4, 5}; 2196 constexpr auto s = Span{arr}; 2197 2198 { 2199 // Split at begin. 2200 constexpr auto splitAt0Result = s.SplitAt(0); 2201 static_assert( 2202 std::is_same_v<Span<const int>, decltype(splitAt0Result.first)>); 2203 static_assert( 2204 std::is_same_v<Span<const int>, decltype(splitAt0Result.second)>); 2205 ASSERT_EQ(s.Elements(), splitAt0Result.second.Elements()); 2206 } 2207 2208 { 2209 // Split at end. 2210 constexpr auto splitAt5Result = s.SplitAt(s.Length()); 2211 static_assert( 2212 std::is_same_v<Span<const int>, decltype(splitAt5Result.first)>); 2213 static_assert( 2214 std::is_same_v<Span<const int>, decltype(splitAt5Result.second)>); 2215 ASSERT_EQ(s.Elements(), splitAt5Result.first.Elements()); 2216 } 2217 2218 { 2219 // Split inside. 2220 constexpr auto splitAt3Result = s.SplitAt(3); 2221 static_assert( 2222 std::is_same_v<Span<const int>, decltype(splitAt3Result.first)>); 2223 static_assert( 2224 std::is_same_v<Span<const int>, decltype(splitAt3Result.second)>); 2225 ASSERT_EQ(s.Elements(), splitAt3Result.first.Elements()); 2226 ASSERT_EQ(s.Elements() + 3, splitAt3Result.second.Elements()); 2227 } 2228 } 2229 2230 SPAN_TEST(split_at_static) { 2231 static constexpr int arr[5] = {1, 2, 3, 4, 5}; 2232 constexpr auto s = Span{arr}; 2233 2234 // Split at begin. 2235 constexpr auto splitAt0Result = s.SplitAt<0>(); 2236 static_assert( 2237 std::is_same_v<Span<const int, 0>, decltype(splitAt0Result.first)>); 2238 static_assert( 2239 std::is_same_v<Span<const int, 5>, decltype(splitAt0Result.second)>); 2240 static_assert(splitAt0Result.second.Elements() == s.Elements()); 2241 2242 // Split at end. 2243 constexpr auto splitAt5Result = s.SplitAt<s.Length()>(); 2244 static_assert(std::is_same_v<Span<const int, s.Length()>, 2245 decltype(splitAt5Result.first)>); 2246 static_assert( 2247 std::is_same_v<Span<const int, 0>, decltype(splitAt5Result.second)>); 2248 static_assert(splitAt5Result.first.Elements() == s.Elements()); 2249 2250 // Split inside. 2251 constexpr auto splitAt3Result = s.SplitAt<3>(); 2252 static_assert( 2253 std::is_same_v<Span<const int, 3>, decltype(splitAt3Result.first)>); 2254 static_assert( 2255 std::is_same_v<Span<const int, 2>, decltype(splitAt3Result.second)>); 2256 static_assert(splitAt3Result.first.Elements() == s.Elements()); 2257 static_assert(splitAt3Result.second.Elements() == s.Elements() + 3); 2258 } 2259 2260 SPAN_TEST(as_const_dynamic) { 2261 static int arr[5] = {1, 2, 3, 4, 5}; 2262 auto span = Span{arr, 5}; 2263 auto constSpan = span.AsConst(); 2264 static_assert(std::is_same_v<Span<const int>, decltype(constSpan)>); 2265 } 2266 2267 SPAN_TEST(as_const_static) { 2268 { 2269 static constexpr int constArr[5] = {1, 2, 3, 4, 5}; 2270 constexpr auto span = Span{constArr}; // is already a Span<const int> 2271 constexpr auto constSpan = span.AsConst(); 2272 2273 static_assert( 2274 std::is_same_v<const Span<const int, 5>, decltype(constSpan)>); 2275 } 2276 2277 { 2278 static int arr[5] = {1, 2, 3, 4, 5}; 2279 auto span = Span{arr}; 2280 auto constSpan = span.AsConst(); 2281 static_assert(std::is_same_v<Span<const int, 5>, decltype(constSpan)>); 2282 } 2283 } 2284 2285 SPAN_TEST(construct_from_iterators_dynamic) { 2286 const int constArr[5] = {1, 2, 3, 4, 5}; 2287 auto constSpan = Span{constArr}; 2288 2289 // const from const 2290 { 2291 const auto wholeSpan = Span{constSpan.cbegin(), constSpan.cend()}; 2292 static_assert(std::is_same_v<decltype(wholeSpan), const Span<const int>>); 2293 ASSERT_TRUE(constSpan == wholeSpan); 2294 2295 const auto emptyBeginSpan = Span{constSpan.cbegin(), constSpan.cbegin()}; 2296 ASSERT_TRUE(emptyBeginSpan.IsEmpty()); 2297 2298 const auto emptyEndSpan = Span{constSpan.cend(), constSpan.cend()}; 2299 ASSERT_TRUE(emptyEndSpan.IsEmpty()); 2300 2301 const auto subSpan = Span{constSpan.cbegin() + 1, constSpan.cend() - 1}; 2302 ASSERT_EQ(constSpan.Length() - 2, subSpan.Length()); 2303 ASSERT_EQ(constSpan.Elements() + 1, subSpan.Elements()); 2304 } 2305 2306 int arr[5] = {1, 2, 3, 4, 5}; 2307 auto span = Span{arr}; 2308 2309 // const from non-const 2310 { 2311 const auto wholeSpan = Span{span.cbegin(), span.cend()}; 2312 static_assert(std::is_same_v<decltype(wholeSpan), const Span<const int>>); 2313 // XXX Can't use span == wholeSpan because of difference in constness. 2314 ASSERT_EQ(span.Elements(), wholeSpan.Elements()); 2315 ASSERT_EQ(span.Length(), wholeSpan.Length()); 2316 2317 const auto emptyBeginSpan = Span{span.cbegin(), span.cbegin()}; 2318 ASSERT_TRUE(emptyBeginSpan.IsEmpty()); 2319 2320 const auto emptyEndSpan = Span{span.cend(), span.cend()}; 2321 ASSERT_TRUE(emptyEndSpan.IsEmpty()); 2322 2323 const auto subSpan = Span{span.cbegin() + 1, span.cend() - 1}; 2324 ASSERT_EQ(span.Length() - 2, subSpan.Length()); 2325 ASSERT_EQ(span.Elements() + 1, subSpan.Elements()); 2326 } 2327 2328 // non-const from non-const 2329 { 2330 const auto wholeSpan = Span{span.begin(), span.end()}; 2331 static_assert(std::is_same_v<decltype(wholeSpan), const Span<int>>); 2332 ASSERT_TRUE(span == wholeSpan); 2333 2334 const auto emptyBeginSpan = Span{span.begin(), span.begin()}; 2335 ASSERT_TRUE(emptyBeginSpan.IsEmpty()); 2336 2337 const auto emptyEndSpan = Span{span.end(), span.end()}; 2338 ASSERT_TRUE(emptyEndSpan.IsEmpty()); 2339 2340 const auto subSpan = Span{span.begin() + 1, span.end() - 1}; 2341 ASSERT_EQ(span.Length() - 2, subSpan.Length()); 2342 } 2343 } 2344 2345 SPAN_TEST(construct_from_iterators_static) { 2346 static constexpr int arr[5] = {1, 2, 3, 4, 5}; 2347 constexpr auto constSpan = Span{arr}; 2348 2349 // const 2350 { 2351 const auto wholeSpan = Span{constSpan.cbegin(), constSpan.cend()}; 2352 static_assert(std::is_same_v<decltype(wholeSpan), const Span<const int>>); 2353 ASSERT_TRUE(constSpan == wholeSpan); 2354 2355 const auto emptyBeginSpan = Span{constSpan.cbegin(), constSpan.cbegin()}; 2356 ASSERT_TRUE(emptyBeginSpan.IsEmpty()); 2357 2358 const auto emptyEndSpan = Span{constSpan.cend(), constSpan.cend()}; 2359 ASSERT_TRUE(emptyEndSpan.IsEmpty()); 2360 2361 const auto subSpan = Span{constSpan.cbegin() + 1, constSpan.cend() - 1}; 2362 ASSERT_EQ(constSpan.Length() - 2, subSpan.Length()); 2363 ASSERT_EQ(constSpan.Elements() + 1, subSpan.Elements()); 2364 } 2365 } 2366 2367 SPAN_TEST(construct_from_container_with_type_deduction) { 2368 std::vector<int> vec = {1, 2, 3, 4, 5}; 2369 2370 // from const 2371 { 2372 const auto& constVecRef = vec; 2373 2374 auto span = Span{constVecRef}; 2375 static_assert(std::is_same_v<decltype(span), Span<const int>>); 2376 } 2377 2378 // from non-const 2379 { 2380 auto span = Span{vec}; 2381 static_assert(std::is_same_v<decltype(span), Span<int>>); 2382 } 2383 }