xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.all/all.pass.cpp (revision ba2236d3000645d3127f972aa7ac1844c47e299c)
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 
11 // std::views::all;
12 
13 #include <ranges>
14 
15 #include <cassert>
16 #include <concepts>
17 #include <type_traits>
18 #include <utility>
19 
20 #include "test_iterators.h"
21 #include "test_macros.h"
22 #include "test_range.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;
ViewView30   constexpr explicit View(int start) : start_(start) {}
31   View(View&&) noexcept(IsNoexcept) = default;
32   View& operator=(View&&) noexcept(IsNoexcept) = default;
beginView33   constexpr int* begin() const { return globalBuff + start_; }
endView34   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;
CopyableViewCopyableView45   constexpr explicit CopyableView(int start) noexcept : start_(start) {}
beginCopyableView46   constexpr int* begin() const { return globalBuff + start_; }
endCopyableView47   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 MoveOnlyView : std::ranges::view_base{
53   MoveOnlyView() = default;
54   MoveOnlyView(const MoveOnlyView&) = delete;
55   MoveOnlyView& operator=(const MoveOnlyView&) = delete;
56   MoveOnlyView(MoveOnlyView&&) = default;
57   MoveOnlyView& operator=(MoveOnlyView&&) = default;
58 
59   int* begin() const;
60   int* end() const;
61 };
62 
63 struct Range {
64   int start_;
RangeRange65   constexpr explicit Range(int start) noexcept : start_(start) {}
beginRange66   constexpr int* begin() const { return globalBuff + start_; }
endRange67   constexpr int* end() const { return globalBuff + 8; }
68 };
69 
70 struct BorrowableRange {
71   int start_;
BorrowableRangeBorrowableRange72   constexpr explicit BorrowableRange(int start) noexcept : start_(start) {}
beginBorrowableRange73   constexpr int* begin() const { return globalBuff + start_; }
endBorrowableRange74   constexpr int* end() const { return globalBuff + 8; }
75 };
76 template<>
77 inline constexpr bool std::ranges::enable_borrowed_range<BorrowableRange> = true;
78 
79 struct RandomAccessRange {
beginRandomAccessRange80   constexpr auto begin() { return random_access_iterator<int*>(globalBuff); }
endRandomAccessRange81   constexpr auto end() { return sized_sentinel(random_access_iterator<int*>(globalBuff + 8)); }
82 };
83 template<>
84 inline constexpr bool std::ranges::enable_borrowed_range<RandomAccessRange> = true;
85 
test()86 constexpr bool test() {
87   {
88     ASSERT_SAME_TYPE(decltype(std::views::all(View<true>())), View<true>);
89     static_assert(noexcept(std::views::all(View<true>())));
90     static_assert(!noexcept(std::views::all(View<false>())));
91 
92     auto viewCopy = std::views::all(View<true>(2));
93     ASSERT_SAME_TYPE(decltype(viewCopy), View<true>);
94     assert(std::ranges::begin(viewCopy) == globalBuff + 2);
95     assert(std::ranges::end(viewCopy) == globalBuff + 8);
96   }
97 
98   {
99     ASSERT_SAME_TYPE(decltype(std::views::all(std::declval<const CopyableView<true>&>())), CopyableView<true>);
100     static_assert(noexcept(std::views::all(CopyableView<true>())));
101     static_assert(!noexcept(std::views::all(CopyableView<false>())));
102 
103     CopyableView<true> view(2);
104     auto viewCopy = std::views::all(view);
105     ASSERT_SAME_TYPE(decltype(viewCopy), CopyableView<true>);
106     assert(std::ranges::begin(viewCopy) == globalBuff + 2);
107     assert(std::ranges::end(viewCopy) == globalBuff + 8);
108   }
109 
110   {
111     Range range(2);
112     auto ref = std::views::all(range);
113     ASSERT_SAME_TYPE(decltype(ref), std::ranges::ref_view<Range>);
114     assert(std::ranges::begin(ref) == globalBuff + 2);
115     assert(std::ranges::end(ref) == globalBuff + 8);
116 
117     auto own = std::views::all(std::move(range));
118     ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<Range>);
119     assert(std::ranges::begin(own) == globalBuff + 2);
120     assert(std::ranges::end(own) == globalBuff + 8);
121 
122     auto cref = std::views::all(std::as_const(range));
123     ASSERT_SAME_TYPE(decltype(cref), std::ranges::ref_view<const Range>);
124     assert(std::ranges::begin(cref) == globalBuff + 2);
125     assert(std::ranges::end(cref) == globalBuff + 8);
126 
127     static_assert(!std::is_invocable_v<decltype(std::views::all), const Range&&>);
128   }
129 
130   {
131     auto own = std::views::all(BorrowableRange(2));
132     ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<BorrowableRange>);
133     assert(std::ranges::begin(own) == globalBuff + 2);
134     assert(std::ranges::end(own) == globalBuff + 8);
135   }
136 
137   {
138     auto own = std::views::all(RandomAccessRange());
139     ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<RandomAccessRange>);
140     assert(base(std::ranges::begin(own)) == globalBuff);
141     assert(base(base(std::ranges::end(own))) == globalBuff + 8);
142   }
143 
144   // Check SFINAE friendliness of the call operator
145   {
146     static_assert(!std::is_invocable_v<decltype(std::views::all)>);
147     static_assert(!std::is_invocable_v<decltype(std::views::all), RandomAccessRange, RandomAccessRange>);
148 
149     // `views::all(v)` is expression equivalent to `decay-copy(v)` if the decayed type
150     // of `v` models `view`. If `v` is an lvalue-reference to a move-only view, the
151     // expression should be ill-formed because `v` is not copyable
152     static_assert(!std::is_invocable_v<decltype(std::views::all), MoveOnlyView&>);
153   }
154 
155   // Test that std::views::all is a range adaptor
156   {
157     // Test `v | views::all`
158     {
159       Range range(0);
160       auto result = range | std::views::all;
161       ASSERT_SAME_TYPE(decltype(result), std::ranges::ref_view<Range>);
162       assert(&result.base() == &range);
163     }
164 
165     // Test `adaptor | views::all`
166     {
167       Range range(0);
168       auto f = [](int i) { return i; };
169       auto const partial = std::views::transform(f) | std::views::all;
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     // Test `views::all | adaptor`
176     {
177       Range range(0);
178       auto f = [](int i) { return i; };
179       auto const partial = std::views::all | std::views::transform(f);
180       using Result = std::ranges::transform_view<std::ranges::ref_view<Range>, decltype(f)>;
181       std::same_as<Result> auto result = partial(range);
182       assert(&result.base().base() == &range);
183     }
184 
185     {
186       struct NotAView { };
187       static_assert( CanBePiped<Range&,    decltype(std::views::all)>);
188       static_assert(!CanBePiped<NotAView,  decltype(std::views::all)>);
189     }
190   }
191 
192   {
193     static_assert(std::same_as<decltype(std::views::all), decltype(std::ranges::views::all)>);
194   }
195 
196   return true;
197 }
198 
main(int,char **)199 int main(int, char**) {
200   test();
201   static_assert(test());
202 
203   return 0;
204 }
205