176 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// std::views::reverse12 13#include <ranges>14 15#include <cassert>16#include <concepts>17#include <iterator>18#include <utility>19 20#include "test_range.h"21#include "types.h"22 23constexpr bool test() {24 int buf[] = {1, 2, 3};25 26 // views::reverse(x) is equivalent to x.base() if x is a reverse_view27 {28 {29 BidirRange view(buf, buf + 3);30 std::ranges::reverse_view<BidirRange> reversed(view);31 std::same_as<BidirRange> auto result = std::views::reverse(reversed);32 assert(result.begin_ == buf);33 assert(result.end_ == buf + 3);34 }35 {36 // Common use case is worth testing37 BidirRange view(buf, buf + 3);38 std::same_as<BidirRange> auto result = std::views::reverse(std::views::reverse(view));39 assert(result.begin_ == buf);40 assert(result.end_ == buf + 3);41 }42 }43 44 // views::reverse(x) is equivalent to subrange{end, begin, size} if x is a45 // sized subrange over reverse iterators46 {47 using It = bidirectional_iterator<int*>;48 using Subrange = std::ranges::subrange<It, It, std::ranges::subrange_kind::sized>;49 50 using ReverseIt = std::reverse_iterator<It>;51 using ReverseSubrange = std::ranges::subrange<ReverseIt, ReverseIt, std::ranges::subrange_kind::sized>;52 53 {54 BidirRange view(buf, buf + 3);55 ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);56 std::same_as<Subrange> auto result = std::views::reverse(subrange);57 assert(base(result.begin()) == buf);58 assert(base(result.end()) == buf + 3);59 }60 {61 // std::move into views::reverse62 BidirRange view(buf, buf + 3);63 ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);64 std::same_as<Subrange> auto result = std::views::reverse(std::move(subrange));65 assert(base(result.begin()) == buf);66 assert(base(result.end()) == buf + 3);67 }68 {69 // with a const subrange70 BidirRange view(buf, buf + 3);71 ReverseSubrange const subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);72 std::same_as<Subrange> auto result = std::views::reverse(subrange);73 assert(base(result.begin()) == buf);74 assert(base(result.end()) == buf + 3);75 }76 }77 78 // views::reverse(x) is equivalent to subrange{end, begin} if x is an79 // unsized subrange over reverse iterators80 {81 using It = bidirectional_iterator<int*>;82 using Subrange = std::ranges::subrange<It, It, std::ranges::subrange_kind::unsized>;83 84 using ReverseIt = std::reverse_iterator<It>;85 using ReverseSubrange = std::ranges::subrange<ReverseIt, ReverseIt, std::ranges::subrange_kind::unsized>;86 87 {88 BidirRange view(buf, buf + 3);89 ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));90 std::same_as<Subrange> auto result = std::views::reverse(subrange);91 assert(base(result.begin()) == buf);92 assert(base(result.end()) == buf + 3);93 }94 {95 // std::move into views::reverse96 BidirRange view(buf, buf + 3);97 ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));98 std::same_as<Subrange> auto result = std::views::reverse(std::move(subrange));99 assert(base(result.begin()) == buf);100 assert(base(result.end()) == buf + 3);101 }102 {103 // with a const subrange104 BidirRange view(buf, buf + 3);105 ReverseSubrange const subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));106 std::same_as<Subrange> auto result = std::views::reverse(subrange);107 assert(base(result.begin()) == buf);108 assert(base(result.end()) == buf + 3);109 }110 }111 112 // Otherwise, views::reverse(x) is equivalent to ranges::reverse_view{x}113 {114 BidirRange view(buf, buf + 3);115 std::same_as<std::ranges::reverse_view<BidirRange>> auto result = std::views::reverse(view);116 assert(base(result.begin().base()) == buf + 3);117 assert(base(result.end().base()) == buf);118 }119 120 // Test that std::views::reverse is a range adaptor121 {122 // Test `v | views::reverse`123 {124 BidirRange view(buf, buf + 3);125 std::same_as<std::ranges::reverse_view<BidirRange>> auto result = view | std::views::reverse;126 assert(base(result.begin().base()) == buf + 3);127 assert(base(result.end().base()) == buf);128 }129 130 // Test `adaptor | views::reverse`131 {132 BidirRange view(buf, buf + 3);133 auto f = [](int i) { return i; };134 auto const partial = std::views::transform(f) | std::views::reverse;135 using Result = std::ranges::reverse_view<std::ranges::transform_view<BidirRange, decltype(f)>>;136 std::same_as<Result> auto result = partial(view);137 assert(base(result.begin().base().base()) == buf + 3);138 assert(base(result.end().base().base()) == buf);139 }140 141 // Test `views::reverse | adaptor`142 {143 BidirRange view(buf, buf + 3);144 auto f = [](int i) { return i; };145 auto const partial = std::views::reverse | std::views::transform(f);146 using Result = std::ranges::transform_view<std::ranges::reverse_view<BidirRange>, decltype(f)>;147 std::same_as<Result> auto result = partial(view);148 assert(base(result.begin().base().base()) == buf + 3);149 assert(base(result.end().base().base()) == buf);150 }151 152 // Check SFINAE friendliness153 {154 struct NotABidirRange { };155 static_assert(!std::is_invocable_v<decltype(std::views::reverse)>);156 static_assert(!std::is_invocable_v<decltype(std::views::reverse), NotABidirRange>);157 static_assert( CanBePiped<BidirRange, decltype(std::views::reverse)>);158 static_assert( CanBePiped<BidirRange&, decltype(std::views::reverse)>);159 static_assert(!CanBePiped<NotABidirRange, decltype(std::views::reverse)>);160 }161 }162 163 {164 static_assert(std::same_as<decltype(std::views::reverse), decltype(std::ranges::views::reverse)>);165 }166 167 return true;168}169 170int main(int, char**) {171 test();172 static_assert(test());173 174 return 0;175}176