brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · 99c1419 Raw
153 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 reverse_iterator<iterator_t<V>> begin();12// constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;13// constexpr auto begin() const requires common_range<const V>;14 15#include <ranges>16#include <cassert>17 18#include "test_macros.h"19#include "types.h"20 21static int globalCount = 0;22 23struct CountedIter {24    typedef std::bidirectional_iterator_tag iterator_category;25    typedef int                             value_type;26    typedef std::ptrdiff_t                  difference_type;27    typedef int*                            pointer;28    typedef int&                            reference;29    typedef CountedIter                     self;30 31    pointer ptr_;32    CountedIter(pointer ptr) : ptr_(ptr) {}33    CountedIter() = default;34 35    reference operator*() const;36    pointer operator->() const;37    auto operator<=>(const self&) const = default;38 39    self& operator++() { globalCount++; ++ptr_; return *this; }40    self operator++(int) {41      auto tmp = *this;42      ++*this;43      return tmp;44    }45 46    self& operator--();47    self operator--(int);48};49 50struct CountedView : std::ranges::view_base {51  int* begin_;52  int* end_;53 54  CountedView(int* b, int* e) : begin_(b), end_(e) { }55 56  auto begin() { return CountedIter(begin_); }57  auto begin() const { return CountedIter(begin_); }58  auto end() { return sentinel_wrapper<CountedIter>(CountedIter(end_)); }59  auto end() const { return sentinel_wrapper<CountedIter>(CountedIter(end_)); }60};61 62struct RASentRange : std::ranges::view_base {63  using sent_t = sentinel_wrapper<random_access_iterator<int*>>;64  using sent_const_t = sentinel_wrapper<random_access_iterator<const int*>>;65 66  int* begin_;67  int* end_;68 69  constexpr RASentRange(int* b, int* e) : begin_(b), end_(e) { }70 71  constexpr random_access_iterator<int*> begin() { return random_access_iterator<int*>{begin_}; }72  constexpr random_access_iterator<const int*> begin() const { return random_access_iterator<const int*>{begin_}; }73  constexpr sent_t end() { return sent_t{random_access_iterator<int*>{end_}}; }74  constexpr sent_const_t end() const { return sent_const_t{random_access_iterator<const int*>{end_}}; }75};76 77template<class T>78concept BeginInvocable = requires(T t) { t.begin(); };79 80constexpr bool test() {81  int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};82 83  // Common bidirectional range.84  {85    auto rev = std::ranges::reverse_view(BidirRange{buffer, buffer + 8});86    assert(base(rev.begin().base()) == buffer + 8);87    assert(base(std::move(rev).begin().base()) == buffer + 8);88 89    ASSERT_SAME_TYPE(decltype(rev.begin()), std::reverse_iterator<bidirectional_iterator<int*>>);90    ASSERT_SAME_TYPE(decltype(std::move(rev).begin()), std::reverse_iterator<bidirectional_iterator<int*>>);91  }92  // Const common bidirectional range.93  {94    const auto rev = std::ranges::reverse_view(BidirRange{buffer, buffer + 8});95    assert(base(rev.begin().base()) == buffer + 8);96    assert(base(std::move(rev).begin().base()) == buffer + 8);97 98    ASSERT_SAME_TYPE(decltype(rev.begin()), std::reverse_iterator<bidirectional_iterator<const int*>>);99    ASSERT_SAME_TYPE(decltype(std::move(rev).begin()), std::reverse_iterator<bidirectional_iterator<const int*>>);100  }101  // Non-common, non-const (move only) bidirectional range.102  {103    auto rev = std::ranges::reverse_view(BidirSentRange<MoveOnly>{buffer, buffer + 8});104    assert(base(std::move(rev).begin().base()) == buffer + 8);105 106    ASSERT_SAME_TYPE(decltype(std::move(rev).begin()), std::reverse_iterator<bidirectional_iterator<int*>>);107  }108  // Non-common, non-const bidirectional range.109  {110    auto rev = std::ranges::reverse_view(BidirSentRange<Copyable>{buffer, buffer + 8});111    assert(base(rev.begin().base()) == buffer + 8);112    assert(base(std::move(rev).begin().base()) == buffer + 8);113 114    ASSERT_SAME_TYPE(decltype(rev.begin()), std::reverse_iterator<bidirectional_iterator<int*>>);115    ASSERT_SAME_TYPE(decltype(std::move(rev).begin()), std::reverse_iterator<bidirectional_iterator<int*>>);116  }117  // Non-common random access range.118  // Note: const overload invalid for non-common ranges, though it would not be impossible119  // to implement for random access ranges.120  {121    auto rev = std::ranges::reverse_view(RASentRange{buffer, buffer + 8});122    assert(base(rev.begin().base()) == buffer + 8);123    assert(base(std::move(rev).begin().base()) == buffer + 8);124 125    ASSERT_SAME_TYPE(decltype(rev.begin()), std::reverse_iterator<random_access_iterator<int*>>);126    ASSERT_SAME_TYPE(decltype(std::move(rev).begin()), std::reverse_iterator<random_access_iterator<int*>>);127  }128  {129    static_assert( BeginInvocable<      std::ranges::reverse_view<BidirSentRange<Copyable>>>);130    static_assert(!BeginInvocable<const std::ranges::reverse_view<BidirSentRange<Copyable>>>);131  }132 133  return true;134}135 136int main(int, char**) {137  test();138  static_assert(test());139 140  {141    // Make sure we cache begin.142    int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};143    CountedView view{buffer, buffer + 8};144    std::ranges::reverse_view rev(view);145    assert(rev.begin().base().ptr_ == buffer + 8);146    assert(globalCount == 8);147    assert(rev.begin().base().ptr_ == buffer + 8);148    assert(globalCount == 8);149  }150 151  return 0;152}153