tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }