brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.4 KiB · d2d1d31 Raw
157 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++17, c++2010 11// <ranges>12 13// constexpr iterator begin();14 15#include <ranges>16 17#include <cassert>18#include <utility>19 20#include "test_iterators.h"21#include "types.h"22 23struct Range : std::ranges::view_base {24  using Iterator = forward_iterator<int*>;25  using Sentinel = sentinel_wrapper<Iterator>;26  constexpr explicit Range(int* b, int* e) : begin_(b), end_(e) {}27  constexpr Iterator begin() const { return Iterator(begin_); }28  constexpr Sentinel end() const { return Sentinel(Iterator(end_)); }29 30private:31  int* begin_;32  int* end_;33};34 35struct TrackingPred : TrackInitialization {36  using TrackInitialization::TrackInitialization;37  constexpr bool operator()(int x, int y) { return x != -y; }38};39 40template <class T>41concept HasBegin = requires(T t) { t.begin(); };42 43static_assert(HasBegin<std::ranges::chunk_by_view<Range, TrackingPred>>);44static_assert(!HasBegin<const std::ranges::chunk_by_view<Range, TrackingPred>>);45 46constexpr bool test() {47  int buff[] = {-4, -3, -2, -1, 1, 2, 3, 4};48 49  // Check the return type of `begin()`50  {51    Range range(buff, buff + 1);52    auto pred = [](int, int) { return true; };53    std::ranges::chunk_by_view view(range, pred);54    using ChunkByIterator = std::ranges::iterator_t<decltype(view)>;55    ASSERT_SAME_TYPE(ChunkByIterator, decltype(view.begin()));56  }57 58  // begin() over an empty range59  {60    Range range(buff, buff);61    auto pred = [](int, int) { return true; };62    std::ranges::chunk_by_view view(range, pred);63    auto it = view.begin();64    assert(it == view.begin());65    assert(it == view.end());66  }67 68  // begin() over a 1-element range69  {70    Range range(buff, buff + 1);71    auto pred = [](int x, int y) { return x == y; };72    std::ranges::chunk_by_view view(range, pred);73    auto it = view.begin();74    assert(base((*it).begin()) == buff);75    assert(base((*it).end()) == buff + 1);76  }77 78  // begin() over a 2-element range79  {80    Range range(buff, buff + 2);81    auto pred = [](int x, int y) { return x == y; };82    std::ranges::chunk_by_view view(range, pred);83    auto it = view.begin();84    assert(base((*it).begin()) == buff);85    assert(base((*it).end()) == buff + 1);86    assert(base((*++it).begin()) == buff + 1);87    assert(base((*it).end()) == buff + 2);88  }89 90  // begin() over a longer range91  {92    Range range(buff, buff + 8);93    auto pred = [](int x, int y) { return x != -y; };94    std::ranges::chunk_by_view view(range, pred);95    auto it = view.begin();96    assert(base((*it).end()) == buff + 4);97  }98 99  // Make sure we do not make a copy of the predicate when we call begin()100  // (we should be passing it to ranges::adjacent_find using std::ref)101  {102    bool moved = false, copied = false;103    Range range(buff, buff + 2);104    std::ranges::chunk_by_view view(range, TrackingPred(&moved, &copied));105    std::exchange(moved, false);106    [[maybe_unused]] auto it = view.begin();107    assert(!moved);108    assert(!copied);109  }110 111  // Test with a non-const predicate112  {113    Range range(buff, buff + 8);114    auto pred = [](int x, int y) mutable { return x != -y; };115    std::ranges::chunk_by_view view(range, pred);116    auto it = view.begin();117    assert(base((*it).end()) == buff + 4);118  }119 120  // Test with a predicate that takes by non-const reference121  {122    Range range(buff, buff + 8);123    auto pred = [](int& x, int& y) { return x != -y; };124    std::ranges::chunk_by_view view(range, pred);125    auto it = view.begin();126    assert(base((*it).end()) == buff + 4);127  }128 129  // Test caching130  {131    // Make sure that we cache the result of begin() on subsequent calls132    Range range(buff, buff + 8);133    int called = 0;134    auto pred  = [&](int x, int y) {135      ++called;136      return x != -y;137    };138 139    std::ranges::chunk_by_view view(range, pred);140    assert(called == 0);141    for (int k = 0; k != 3; ++k) {142      auto it = view.begin();143      assert(base((*it).end()) == buff + 4);144      assert(called == 4); // 4, because the cached iterator is 'buff + 4' (end of the first chunk)145    }146  }147 148  return true;149}150 151int main(int, char**) {152  test();153  static_assert(test());154 155  return 0;156}157