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
24int globalBuff[8];
25
26template<bool IsNoexcept>
27struct 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};
36static_assert(std::ranges::view<View<true>>);
37static_assert(std::ranges::view<View<false>>);
38
39template<bool IsNoexcept>
40struct 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};
49static_assert(std::ranges::view<CopyableView<true>>);
50static_assert(std::ranges::view<CopyableView<false>>);
51
52struct 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
63struct Range {
64 int start_;
65 constexpr explicit Range(int start) noexcept : start_(start) {}
66 constexpr int* begin() const { return globalBuff + start_; }
67 constexpr int* end() const { return globalBuff + 8; }
68};
69
70struct BorrowableRange {
71 int start_;
72 constexpr explicit BorrowableRange(int start) noexcept : start_(start) {}
73 constexpr int* begin() const { return globalBuff + start_; }
74 constexpr int* end() const { return globalBuff + 8; }
75};
76template<>
77inline constexpr bool std::ranges::enable_borrowed_range<BorrowableRange> = true;
78
79struct RandomAccessRange {
80 constexpr auto begin() { return random_access_iterator<int*>(globalBuff); }
81 constexpr auto end() { return sized_sentinel(random_access_iterator<int*>(globalBuff + 8)); }
82};
83template<>
84inline constexpr bool std::ranges::enable_borrowed_range<RandomAccessRange> = true;
85
86constexpr 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
199int main(int, char**) {
200 test();
201 static_assert(test());
202
203 return 0;
204}
205

source code of libcxx/test/std/ranges/range.adaptors/range.all/all.pass.cpp