brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · c1011f3 Raw
145 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// <algorithm>12 13// template<bidirectional_iterator I, sentinel_for<I> S>14//   requires permutable<I>15//   constexpr I ranges::reverse(I first, S last);16// template<bidirectional_range R>17//   requires permutable<iterator_t<R>>18//   constexpr borrowed_iterator_t<R> ranges::reverse(R&& r);19 20#include <algorithm>21#include <array>22#include <concepts>23#include <ranges>24 25#include "almost_satisfies_types.h"26#include "MoveOnly.h"27#include "test_iterators.h"28 29template <class Iter, class Sent = sentinel_wrapper<Iter>>30concept HasReverseIt = requires (Iter first, Sent last) { std::ranges::reverse(first, last); };31 32static_assert(HasReverseIt<int*>);33static_assert(!HasReverseIt<BidirectionalIteratorNotDerivedFrom>);34static_assert(!HasReverseIt<BidirectionalIteratorNotDecrementable>);35static_assert(!HasReverseIt<PermutableNotForwardIterator>);36static_assert(!HasReverseIt<PermutableNotSwappable>);37 38 39template <class Range>40concept HasReverseR = requires (Range range) { std::ranges::reverse(range); };41 42static_assert(HasReverseR<UncheckedRange<int*>>);43static_assert(!HasReverseR<BidirectionalRangeNotDerivedFrom>);44static_assert(!HasReverseR<BidirectionalRangeNotDecrementable>);45static_assert(!HasReverseR<PermutableRangeNotForwardIterator>);46static_assert(!HasReverseR<PermutableRangeNotSwappable>);47 48template <class Iter, class Sent, std::size_t N>49constexpr void test(std::array<int, N> value, std::array<int, N> expected) {50  {51    auto val = value;52    std::same_as<Iter> decltype(auto) ret = std::ranges::reverse(Iter(val.data()), Sent(Iter(val.data() + val.size())));53    assert(val == expected);54    assert(base(ret) == val.data() + val.size());55  }56  {57    auto val = value;58    auto range = std::ranges::subrange(Iter(val.data()), Sent(Iter(val.data() + val.size())));59    std::same_as<Iter> decltype(auto) ret = std::ranges::reverse(range);60    assert(val == expected);61    assert(base(ret) == val.data() + val.size());62  }63}64 65template <class Iter, class Sent = Iter>66constexpr void test_iterators() {67  // simple test68  test<Iter, Sent, 4>({1, 2, 3, 4}, {4, 3, 2, 1});69  // check that an odd number of elements works70  test<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, {7, 6, 5, 4, 3, 2, 1});71  // check that an empty range works72  test<Iter, Sent, 0>({}, {});73  // check that a single element works74  test<Iter, Sent, 1>({5}, {5});75}76 77struct SwapCounter {78  int* counter;79  constexpr SwapCounter(int* counter_) : counter(counter_) {}80  friend constexpr void swap(SwapCounter& lhs, SwapCounter&) { ++*lhs.counter; }81};82 83constexpr bool test() {84  test_iterators<bidirectional_iterator<int*>>();85  test_iterators<bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>();86  test_iterators<random_access_iterator<int*>>();87  test_iterators<random_access_iterator<int*>, sentinel_wrapper<random_access_iterator<int*>>>();88  test_iterators<contiguous_iterator<int*>>();89  test_iterators<contiguous_iterator<int*>, sentinel_wrapper<contiguous_iterator<int*>>>();90  test_iterators<int*>();91 92  test_iterators<ProxyIterator<bidirectional_iterator<int*>>>();93  test_iterators<ProxyIterator<random_access_iterator<int*>>>();94  test_iterators<ProxyIterator<contiguous_iterator<int*>>>();95 96  // check that std::ranges::dangling is returned97  {98    [[maybe_unused]] std::same_as<std::ranges::dangling> auto ret = std::ranges::reverse(std::array {1, 2, 3, 4});99  }100 101  {102    {103      int counter = 0;104      SwapCounter a[] = {&counter, &counter, &counter, &counter};105      std::ranges::reverse(a);106      assert(counter == 2);107    }108    {109      int counter = 0;110      SwapCounter a[] = {&counter, &counter, &counter, &counter};111      std::ranges::reverse(a, a + 4);112      assert(counter == 2);113    }114  }115 116  // Move only types work for ProxyIterator117  {118    {119      MoveOnly a[] = {1, 2, 3};120      ProxyRange proxyA{a};121      std::ranges::reverse(proxyA.begin(), proxyA.end());122      assert(a[0].get() == 3);123      assert(a[1].get() == 2);124      assert(a[2].get() == 1);125    }126    {127      MoveOnly a[] = {1, 2, 3};128      ProxyRange proxyA{a};129      std::ranges::reverse(proxyA);130      assert(a[0].get() == 3);131      assert(a[1].get() == 2);132      assert(a[2].get() == 1);133    }134  }135 136  return true;137}138 139int main(int, char**) {140  test();141  static_assert(test());142 143  return 0;144}145