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