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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: libcpp-no-concepts 11 // UNSUPPORTED: gcc-10 12 // UNSUPPORTED: libcpp-has-no-incomplete-ranges 13 14 // std::views::all; 15 16 #include <ranges> 17 18 #include <cassert> 19 #include "test_macros.h" 20 #include "test_iterators.h" 21 22 int globalBuff[8]; 23 24 template<bool IsNoexcept> 25 struct View : std::ranges::view_base { 26 int start_ = 0; 27 explicit View() noexcept(IsNoexcept) = default; 28 constexpr explicit View(int start) : start_(start) {} 29 View(View&&) noexcept(IsNoexcept) = default; 30 View& operator=(View&&) noexcept(IsNoexcept) = default; 31 friend constexpr int* begin(View& view) { return globalBuff + view.start_; } 32 friend constexpr int* begin(View const& view) { return globalBuff + view.start_; } 33 friend constexpr int* end(View&) { return globalBuff + 8; } 34 friend constexpr int* end(View const&) { return globalBuff + 8; } 35 }; 36 static_assert(std::ranges::view<View<true>>); 37 static_assert(std::ranges::view<View<false>>); 38 39 template<bool IsNoexcept> 40 struct CopyableView : std::ranges::view_base { 41 int start_ = 0; 42 explicit CopyableView() noexcept(IsNoexcept) = default; 43 CopyableView(CopyableView const&) noexcept(IsNoexcept) = default; 44 CopyableView& operator=(CopyableView const&) noexcept(IsNoexcept) = default; 45 constexpr explicit CopyableView(int start) noexcept : start_(start) {} 46 friend constexpr int* begin(CopyableView& view) { return globalBuff + view.start_; } 47 friend constexpr int* begin(CopyableView const& view) { return globalBuff + view.start_; } 48 friend constexpr int* end(CopyableView&) { return globalBuff + 8; } 49 friend constexpr int* end(CopyableView const&) { return globalBuff + 8; } 50 }; 51 static_assert(std::ranges::view<CopyableView<true>>); 52 static_assert(std::ranges::view<CopyableView<false>>); 53 54 struct Range { 55 int start_; 56 constexpr explicit Range(int start) noexcept : start_(start) {} 57 friend constexpr int* begin(Range const& range) { return globalBuff + range.start_; } 58 friend constexpr int* begin(Range& range) { return globalBuff + range.start_; } 59 friend constexpr int* end(Range const&) { return globalBuff + 8; } 60 friend constexpr int* end(Range&) { return globalBuff + 8; } 61 }; 62 63 struct BorrowableRange { 64 int start_; 65 constexpr explicit BorrowableRange(int start) noexcept : start_(start) {} 66 friend constexpr int* begin(BorrowableRange const& range) { return globalBuff + range.start_; } 67 friend constexpr int* begin(BorrowableRange& range) { return globalBuff + range.start_; } 68 friend constexpr int* end(BorrowableRange const&) { return globalBuff + 8; } 69 friend constexpr int* end(BorrowableRange&) { return globalBuff + 8; } 70 }; 71 template<> 72 inline constexpr bool std::ranges::enable_borrowed_range<BorrowableRange> = true; 73 74 struct RandomAccessRange { 75 struct sentinel { 76 friend constexpr bool operator==(sentinel, const random_access_iterator<int*> rai) { return rai.base() == globalBuff + 8; } 77 friend constexpr std::ptrdiff_t operator-(sentinel, random_access_iterator<int*>) { return -8; } 78 friend constexpr std::ptrdiff_t operator-(random_access_iterator<int*>, sentinel) { return 8; } 79 }; 80 81 constexpr random_access_iterator<int*> begin() { return random_access_iterator<int*>{globalBuff}; } 82 constexpr sentinel end() { return {}; } 83 }; 84 template<> 85 inline constexpr bool std::ranges::enable_borrowed_range<RandomAccessRange> = true; 86 87 constexpr bool test() { 88 { 89 ASSERT_SAME_TYPE(decltype(std::views::all(View<true>())), View<true>); 90 static_assert(noexcept(std::views::all(View<true>()))); 91 static_assert(!noexcept(std::views::all(View<false>()))); 92 93 auto viewCopy = std::views::all(View<true>(2)); 94 ASSERT_SAME_TYPE(decltype(viewCopy), View<true>); 95 assert(std::ranges::begin(viewCopy) == globalBuff + 2); 96 assert(std::ranges::end(viewCopy) == globalBuff + 8); 97 } 98 99 { 100 ASSERT_SAME_TYPE(decltype(std::views::all(std::declval<const CopyableView<true>&>())), CopyableView<true>); 101 static_assert(noexcept(std::views::all(CopyableView<true>()))); 102 static_assert(!noexcept(std::views::all(CopyableView<false>()))); 103 104 CopyableView<true> view(2); 105 auto viewCopy = std::views::all(view); 106 ASSERT_SAME_TYPE(decltype(viewCopy), CopyableView<true>); 107 assert(std::ranges::begin(viewCopy) == globalBuff + 2); 108 assert(std::ranges::end(viewCopy) == globalBuff + 8); 109 } 110 111 { 112 Range range(2); 113 auto ref = std::views::all(range); 114 ASSERT_SAME_TYPE(decltype(ref), std::ranges::ref_view<Range>); 115 assert(std::ranges::begin(ref) == globalBuff + 2); 116 assert(std::ranges::end(ref) == globalBuff + 8); 117 118 static_assert(!std::is_invocable_v<decltype(std::views::all), Range>); 119 } 120 121 { 122 const Range range(2); 123 auto ref = std::views::all(range); 124 static_assert(!noexcept(std::views::all(range))); 125 ASSERT_SAME_TYPE(decltype(ref), std::ranges::ref_view<const Range>); 126 assert(std::ranges::begin(ref) == globalBuff + 2); 127 assert(std::ranges::end(ref) == globalBuff + 8); 128 } 129 130 { 131 auto subrange = std::views::all(BorrowableRange(2)); 132 static_assert(!noexcept(std::views::all(BorrowableRange(2)))); 133 ASSERT_SAME_TYPE(decltype(subrange), std::ranges::subrange<int*>); 134 assert(std::ranges::begin(subrange) == globalBuff + 2); 135 assert(std::ranges::end(subrange) == globalBuff + 8); 136 } 137 138 { 139 auto subrange = std::views::all(RandomAccessRange()); 140 ASSERT_SAME_TYPE(decltype(subrange), 141 std::ranges::subrange<random_access_iterator<int*>, RandomAccessRange::sentinel>); 142 assert(std::ranges::begin(subrange).base() == globalBuff); 143 assert(std::ranges::end(subrange) == std::ranges::begin(subrange) + 8); 144 } 145 146 return true; 147 } 148 149 int main(int, char**) { 150 test(); 151 static_assert(test()); 152 153 return 0; 154 } 155