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-has-no-incomplete-ranges 11 12 // std::views::all; 13 14 #include <ranges> 15 16 #include <cassert> 17 #include <concepts> 18 #include <type_traits> 19 #include <utility> 20 21 #include "test_macros.h" 22 #include "test_iterators.h" 23 24 int globalBuff[8]; 25 26 template<bool IsNoexcept> 27 struct View : std::ranges::view_base { 28 int start_ = 0; 29 explicit View() noexcept(IsNoexcept) = default; 30 constexpr explicit View(int start) : start_(start) {} 31 View(View&&) noexcept(IsNoexcept) = default; 32 View& operator=(View&&) noexcept(IsNoexcept) = default; 33 constexpr int* begin() const { return globalBuff + start_; } 34 constexpr int* end() 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 constexpr int* begin() const { return globalBuff + start_; } 47 constexpr int* end() const { return globalBuff + 8; } 48 }; 49 static_assert(std::ranges::view<CopyableView<true>>); 50 static_assert(std::ranges::view<CopyableView<false>>); 51 52 struct Range { 53 int start_; 54 constexpr explicit Range(int start) noexcept : start_(start) {} 55 constexpr int* begin() const { return globalBuff + start_; } 56 constexpr int* end() const { return globalBuff + 8; } 57 }; 58 59 struct BorrowableRange { 60 int start_; 61 constexpr explicit BorrowableRange(int start) noexcept : start_(start) {} 62 constexpr int* begin() const { return globalBuff + start_; } 63 constexpr int* end() const { return globalBuff + 8; } 64 }; 65 template<> 66 inline constexpr bool std::ranges::enable_borrowed_range<BorrowableRange> = true; 67 68 struct RandomAccessRange { 69 constexpr auto begin() { return random_access_iterator<int*>(globalBuff); } 70 constexpr auto end() { return sized_sentinel(random_access_iterator<int*>(globalBuff + 8)); } 71 }; 72 template<> 73 inline constexpr bool std::ranges::enable_borrowed_range<RandomAccessRange> = true; 74 75 template <class View, class T> 76 concept CanBePiped = requires (View&& view, T&& t) { 77 { std::forward<View>(view) | std::forward<T>(t) }; 78 }; 79 80 constexpr bool test() { 81 { 82 ASSERT_SAME_TYPE(decltype(std::views::all(View<true>())), View<true>); 83 static_assert(noexcept(std::views::all(View<true>()))); 84 static_assert(!noexcept(std::views::all(View<false>()))); 85 86 auto viewCopy = std::views::all(View<true>(2)); 87 ASSERT_SAME_TYPE(decltype(viewCopy), View<true>); 88 assert(std::ranges::begin(viewCopy) == globalBuff + 2); 89 assert(std::ranges::end(viewCopy) == globalBuff + 8); 90 } 91 92 { 93 ASSERT_SAME_TYPE(decltype(std::views::all(std::declval<const CopyableView<true>&>())), CopyableView<true>); 94 static_assert(noexcept(std::views::all(CopyableView<true>()))); 95 static_assert(!noexcept(std::views::all(CopyableView<false>()))); 96 97 CopyableView<true> view(2); 98 auto viewCopy = std::views::all(view); 99 ASSERT_SAME_TYPE(decltype(viewCopy), CopyableView<true>); 100 assert(std::ranges::begin(viewCopy) == globalBuff + 2); 101 assert(std::ranges::end(viewCopy) == globalBuff + 8); 102 } 103 104 { 105 Range range(2); 106 auto ref = std::views::all(range); 107 ASSERT_SAME_TYPE(decltype(ref), std::ranges::ref_view<Range>); 108 assert(std::ranges::begin(ref) == globalBuff + 2); 109 assert(std::ranges::end(ref) == globalBuff + 8); 110 111 auto own = std::views::all(std::move(range)); 112 ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<Range>); 113 assert(std::ranges::begin(own) == globalBuff + 2); 114 assert(std::ranges::end(own) == globalBuff + 8); 115 116 auto cref = std::views::all(std::as_const(range)); 117 ASSERT_SAME_TYPE(decltype(cref), std::ranges::ref_view<const Range>); 118 assert(std::ranges::begin(cref) == globalBuff + 2); 119 assert(std::ranges::end(cref) == globalBuff + 8); 120 121 static_assert(!std::is_invocable_v<decltype(std::views::all), const Range&&>); 122 } 123 124 { 125 auto own = std::views::all(BorrowableRange(2)); 126 ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<BorrowableRange>); 127 assert(std::ranges::begin(own) == globalBuff + 2); 128 assert(std::ranges::end(own) == globalBuff + 8); 129 } 130 131 { 132 auto own = std::views::all(RandomAccessRange()); 133 ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<RandomAccessRange>); 134 assert(base(std::ranges::begin(own)) == globalBuff); 135 assert(base(base(std::ranges::end(own))) == globalBuff + 8); 136 } 137 138 // Check SFINAE friendliness of the call operator 139 { 140 static_assert(!std::is_invocable_v<decltype(std::views::all)>); 141 static_assert(!std::is_invocable_v<decltype(std::views::all), RandomAccessRange, RandomAccessRange>); 142 } 143 144 // Test that std::views::all is a range adaptor 145 { 146 // Test `v | views::all` 147 { 148 Range range(0); 149 auto result = range | std::views::all; 150 ASSERT_SAME_TYPE(decltype(result), std::ranges::ref_view<Range>); 151 assert(&result.base() == &range); 152 } 153 154 // Test `adaptor | views::all` 155 { 156 Range range(0); 157 auto f = [](int i) { return i; }; 158 auto const partial = std::views::transform(f) | std::views::all; 159 using Result = std::ranges::transform_view<std::ranges::ref_view<Range>, decltype(f)>; 160 std::same_as<Result> auto result = partial(range); 161 assert(&result.base().base() == &range); 162 } 163 164 // Test `views::all | adaptor` 165 { 166 Range range(0); 167 auto f = [](int i) { return i; }; 168 auto const partial = std::views::all | std::views::transform(f); 169 using Result = std::ranges::transform_view<std::ranges::ref_view<Range>, decltype(f)>; 170 std::same_as<Result> auto result = partial(range); 171 assert(&result.base().base() == &range); 172 } 173 174 { 175 struct NotAView { }; 176 static_assert( CanBePiped<Range&, decltype(std::views::all)>); 177 static_assert(!CanBePiped<NotAView, decltype(std::views::all)>); 178 } 179 } 180 181 { 182 static_assert(std::same_as<decltype(std::views::all), decltype(std::ranges::views::all)>); 183 } 184 185 return true; 186 } 187 188 int main(int, char**) { 189 test(); 190 static_assert(test()); 191 192 return 0; 193 } 194