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