brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · 203b237 Raw
174 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// constexpr auto begin();12 13#include <array>14#include <cassert>15#include <ranges>16#include <type_traits>17#include <utility>18 19#include "test_iterators.h"20 21struct View : std::ranges::view_base {22  int* begin() const;23  int* end() const;24};25 26// Test that begin is not const27template <class T>28concept HasBegin = requires(T t) { t.begin(); };29 30static_assert(HasBegin<std::ranges::split_view<View, View>>);31static_assert(!HasBegin<const std::ranges::split_view<View, View>>);32 33template <template <class> class MakeIter>34constexpr void testOne() {35  constexpr auto make_subrange = []<class T, std::size_t N>(T(&buffer)[N]) {36    using Iter = MakeIter<T*>;37    using Sent = sentinel_wrapper<Iter>;38    return std::ranges::subrange<Iter, Sent>{Iter{buffer}, Sent{Iter{buffer + N}}};39  };40 41  using Iter  = MakeIter<int*>;42  using Sent  = sentinel_wrapper<Iter>;43  using Range = std::ranges::subrange<Iter, Sent>;44 45  // empty view46  {47    std::array<int, 0> a;48    Range range{Iter{a.data()}, Sent{Iter{a.data() + a.size()}}};49    std::ranges::split_view sv{std::move(range), 1};50    auto it         = sv.begin();51    auto firstRange = *it;52    assert(firstRange.begin() == Iter(a.data()));53    assert(firstRange.end() == Sent(Iter(a.data())));54  }55 56  // empty pattern57  {58    int buffer[] = {1, 2, 3};59    auto range   = make_subrange(buffer);60    std::ranges::split_view sv{std::move(range), std::views::empty<int>};61    auto it         = sv.begin();62    auto firstRange = *it;63    assert(firstRange.begin() == Iter(buffer));64    assert(firstRange.end() == Sent(Iter(buffer + 1)));65  }66 67  // empty view and empty pattern68  {69    std::array<int, 0> a;70    Range range{Iter{a.data()}, Sent{Iter{a.data() + a.size()}}};71    std::ranges::split_view sv{std::move(range), std::views::empty<int>};72    auto it         = sv.begin();73    auto firstRange = *it;74    assert(firstRange.begin() == Iter(a.data()));75    assert(firstRange.end() == Sent(Iter(a.data())));76  }77 78  // pattern found at the beginning79  {80    int buffer[]  = {1, 2, 3};81    auto range    = make_subrange(buffer);82    int pattern[] = {1, 2};83    std::ranges::split_view sv{range, pattern};84 85    auto it         = sv.begin();86    auto firstRange = *it;87    assert(firstRange.begin() == Iter(buffer));88    assert(firstRange.end() == Sent(Iter(buffer)));89  }90 91  // pattern found in the middle92  {93    int buffer[]  = {1, 2, 3, 4};94    auto range    = make_subrange(buffer);95    int pattern[] = {2, 3};96    std::ranges::split_view sv{range, pattern};97 98    auto it         = sv.begin();99    auto firstRange = *it;100    assert(firstRange.begin() == Iter(buffer));101    assert(firstRange.end() == Sent(Iter(buffer + 1)));102  }103 104  // pattern found at the end105  {106    int buffer[]  = {1, 2, 3};107    auto range    = make_subrange(buffer);108    int pattern[] = {2, 3};109    std::ranges::split_view sv{range, pattern};110 111    auto it         = sv.begin();112    auto firstRange = *it;113    assert(firstRange.begin() == Iter(buffer));114    assert(firstRange.end() == Sent(Iter(buffer + 1)));115  }116 117  // pattern not found118  {119    int buffer[]  = {1, 2, 3};120    auto range    = make_subrange(buffer);121    int pattern[] = {1, 3};122    std::ranges::split_view sv{range, pattern};123 124    auto it         = sv.begin();125    auto firstRange = *it;126    assert(firstRange.begin() == Iter(buffer));127    assert(firstRange.end() == Sent(Iter(buffer + 3)));128  }129 130  // Make sure that we cache the result of begin() on subsequent calls131  {132    struct Foo {133      int& equalsCalledTimes;134 135      constexpr bool operator==(const Foo&) const {136        ++equalsCalledTimes;137        return true;138      }139    };140 141    int equalsCalledTimes = 0;142    Foo buffer[]          = {Foo{equalsCalledTimes}, Foo{equalsCalledTimes}};143    auto range            = make_subrange(buffer);144 145    std::ranges::split_view sv{range, Foo{equalsCalledTimes}};146 147    assert(equalsCalledTimes == 0);148 149    [[maybe_unused]] auto it1       = sv.begin();150    auto calledTimesAfterFirstBegin = equalsCalledTimes;151    assert(calledTimesAfterFirstBegin != 0);152 153    for (int i = 0; i < 10; ++i) {154      [[maybe_unused]] auto it2 = sv.begin();155      assert(equalsCalledTimes == calledTimesAfterFirstBegin);156    }157  }158}159 160constexpr bool test() {161  testOne<forward_iterator>();162  testOne<bidirectional_iterator>();163  testOne<random_access_iterator>();164  testOne<contiguous_iterator>();165  testOne<std::type_identity_t>();166  return true;167}168 169int main(int, char**) {170  test();171  static_assert(test());172  return 0;173}174