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// REQUIRES: std-at-least-c++23
10
11// <ranges>
12
13// template <input_range V, forward_range Pattern>
14// requires view<V> && input_range<range_reference_t<V>> && view<Pattern> &&
15// compatible-joinable-ranges<range_reference_t<V>, Pattern>
16// class join_with_view;
17
18#include <ranges>
19
20#include <cstddef>
21#include <vector>
22
23#include "test_iterators.h"
24#include "../types.h"
25
26template <class View, class Pattern>
27concept CanFormJoinWithView = requires { typename std::ranges::join_with_view<View, Pattern>; };
28
29// join_with_view is not valid when `V` is not an input_range
30namespace test_when_view_is_not_an_input_range {
31struct View : std::ranges::view_base {
32 using It = cpp20_output_iterator<std::vector<int>*>;
33 It begin();
34 sentinel_wrapper<It> end();
35};
36
37struct Pattern : std::ranges::view_base {
38 int* begin();
39 int* end();
40};
41
42static_assert(std::ranges::range<View>);
43static_assert(!std::ranges::input_range<View>);
44static_assert(std::ranges::view<View>);
45static_assert(std::ranges::forward_range<Pattern>);
46static_assert(std::ranges::view<Pattern>);
47static_assert(!CanFormJoinWithView<View, Pattern>);
48} // namespace test_when_view_is_not_an_input_range
49
50// join_with_view is not valid when `Pattern` is not a forward_range
51namespace test_when_pattern_is_not_a_forward_range {
52struct View : std::ranges::view_base {
53 std::vector<float>* begin();
54 std::vector<float>* end();
55};
56
57struct Pattern : std::ranges::view_base {
58 using It = cpp20_input_iterator<float*>;
59 It begin();
60 sentinel_wrapper<It> end();
61};
62
63static_assert(std::ranges::input_range<View>);
64static_assert(std::ranges::view<View>);
65static_assert(!std::ranges::forward_range<Pattern>);
66static_assert(std::ranges::view<Pattern>);
67static_assert(!CanFormJoinWithView<View, Pattern>);
68} // namespace test_when_pattern_is_not_a_forward_range
69
70// join_with_view is not valid when `V` does not model std::ranges::view
71namespace test_when_view_does_not_model_view {
72struct View {
73 std::vector<double>* begin();
74 std::vector<double>* end();
75};
76
77struct Pattern : std::ranges::view_base {
78 double* begin();
79 double* end();
80};
81
82static_assert(std::ranges::input_range<View>);
83static_assert(!std::ranges::view<View>);
84static_assert(std::ranges::forward_range<Pattern>);
85static_assert(std::ranges::view<Pattern>);
86static_assert(!CanFormJoinWithView<View, Pattern>);
87} // namespace test_when_view_does_not_model_view
88
89// join_with_view is not valid when `range_reference_t` of `V` is not an input_range
90namespace test_when_range_reference_t_of_view_is_not_an_input_range {
91struct InnerRange {
92 using It = cpp20_output_iterator<long*>;
93 It begin();
94 sentinel_wrapper<It> end();
95};
96
97struct View : std::ranges::view_base {
98 InnerRange* begin();
99 InnerRange* end();
100};
101
102struct Pattern : std::ranges::view_base {
103 long* begin();
104 long* end();
105};
106
107static_assert(std::ranges::range<InnerRange>);
108static_assert(!std::ranges::input_range<InnerRange>);
109static_assert(std::ranges::input_range<View>);
110static_assert(std::ranges::view<View>);
111static_assert(std::ranges::forward_range<Pattern>);
112static_assert(std::ranges::view<Pattern>);
113static_assert(!CanFormJoinWithView<View, Pattern>);
114} // namespace test_when_range_reference_t_of_view_is_not_an_input_range
115
116// join_with_view is not valid when `Pattern` does not model std::ranges::view
117namespace test_when_pattern_does_not_model_view {
118struct View : std::ranges::view_base {
119 std::vector<short>* begin();
120 std::vector<short>* end();
121};
122
123struct Pattern {
124 short* begin();
125 short* end();
126};
127
128static_assert(std::ranges::input_range<View>);
129static_assert(std::ranges::view<View>);
130static_assert(std::ranges::forward_range<Pattern>);
131static_assert(!std::ranges::view<Pattern>);
132static_assert(!CanFormJoinWithView<View, Pattern>);
133} // namespace test_when_pattern_does_not_model_view
134
135// join_with_view is not valid when `range_reference_t<View>` and pattern
136// does not model together compatible-joinable-ranges
137namespace test_when_used_ranges_are_not_concatable {
138using std::ranges::range_reference_t;
139using std::ranges::range_rvalue_reference_t;
140using std::ranges::range_value_t;
141
142template <class InnerRange>
143struct View : std::ranges::view_base {
144 InnerRange* begin();
145 InnerRange* end();
146};
147
148namespace no_concat_reference_t {
149struct ValueType {};
150
151struct InnerRange {
152 struct It {
153 using difference_type = std::ptrdiff_t;
154 using value_type = ValueType;
155 struct reference {
156 operator value_type();
157 };
158
159 It& operator++();
160 void operator++(int);
161 reference operator*() const;
162 };
163
164 It begin();
165 sentinel_wrapper<It> end();
166};
167
168struct Pattern : std::ranges::view_base {
169 struct It {
170 using difference_type = std::ptrdiff_t;
171 using value_type = ValueType;
172 struct reference {
173 operator value_type();
174 };
175
176 It& operator++();
177 It operator++(int);
178 reference operator*() const;
179 bool operator==(const It&) const;
180 friend value_type&& iter_move(const It&);
181 };
182
183 It begin();
184 It end();
185};
186
187static_assert(std::ranges::input_range<InnerRange>);
188static_assert(std::ranges::forward_range<Pattern>);
189static_assert(std::ranges::view<Pattern>);
190static_assert(!std::common_reference_with<range_reference_t<InnerRange>, range_reference_t<Pattern>>);
191static_assert(std::common_with<range_value_t<InnerRange>, range_value_t<Pattern>>);
192static_assert(std::common_reference_with<range_rvalue_reference_t<InnerRange>, range_rvalue_reference_t<Pattern>>);
193static_assert(!CanFormJoinWithView<View<InnerRange>, Pattern>);
194} // namespace no_concat_reference_t
195
196namespace no_concat_value_t {
197struct InnerRange {
198 struct It {
199 using difference_type = std::ptrdiff_t;
200 struct value_type {};
201
202 struct reference {
203 operator value_type();
204 operator float();
205 };
206
207 It& operator++();
208 void operator++(int);
209 reference operator*() const;
210 };
211
212 It begin();
213 sentinel_wrapper<It> end();
214};
215
216struct Pattern : std::ranges::view_base {
217 const float* begin();
218 const float* end();
219};
220
221static_assert(std::ranges::input_range<InnerRange>);
222static_assert(std::ranges::forward_range<Pattern>);
223static_assert(std::ranges::view<Pattern>);
224static_assert(std::common_reference_with<range_reference_t<InnerRange>, range_reference_t<Pattern>>);
225static_assert(!std::common_with<range_value_t<InnerRange>, range_value_t<Pattern>>);
226static_assert(std::common_reference_with<range_rvalue_reference_t<InnerRange>, range_rvalue_reference_t<Pattern>>);
227static_assert(!CanFormJoinWithView<View<InnerRange>, Pattern>);
228} // namespace no_concat_value_t
229
230namespace no_concat_rvalue_reference_t {
231struct InnerRange {
232 using It = cpp20_input_iterator<int*>;
233 It begin();
234 sentinel_wrapper<It> end();
235};
236
237struct Pattern : std::ranges::view_base {
238 struct It {
239 using difference_type = std::ptrdiff_t;
240 struct value_type {
241 operator int() const;
242 };
243
244 struct rvalue_reference {
245 operator value_type();
246 };
247
248 It& operator++();
249 It operator++(int);
250 value_type& operator*() const;
251 bool operator==(const It&) const;
252 friend rvalue_reference iter_move(const It&);
253 };
254
255 It begin();
256 It end();
257};
258
259static_assert(std::ranges::input_range<InnerRange>);
260static_assert(std::ranges::forward_range<Pattern>);
261static_assert(std::ranges::view<Pattern>);
262static_assert(std::common_reference_with<range_reference_t<InnerRange>, range_reference_t<Pattern>>);
263static_assert(std::common_with<range_value_t<InnerRange>, range_value_t<Pattern>>);
264static_assert(!std::common_reference_with<range_rvalue_reference_t<InnerRange>, range_rvalue_reference_t<Pattern>>);
265static_assert(!CanFormJoinWithView<View<InnerRange>, Pattern>);
266} // namespace no_concat_rvalue_reference_t
267
268namespace not_concat_indirectly_readable { // Required after LWG-4074 ("compatible-joinable-ranges is underconstrained")
269struct InnerRange {
270 using It = cpp20_input_iterator<int*>;
271 It begin();
272 sentinel_wrapper<It> end();
273};
274
275struct Pattern : std::ranges::view_base {
276 lwg4074::Iter begin();
277 lwg4074::Iter end();
278};
279
280static_assert(std::ranges::input_range<InnerRange>);
281static_assert(std::ranges::forward_range<Pattern>);
282static_assert(std::ranges::view<Pattern>);
283static_assert(std::common_reference_with<range_reference_t<InnerRange>, range_reference_t<Pattern>>);
284static_assert(std::common_with<range_value_t<InnerRange>, range_value_t<Pattern>>);
285static_assert(std::common_reference_with<range_rvalue_reference_t<InnerRange>, range_rvalue_reference_t<Pattern>>);
286LIBCPP_STATIC_ASSERT(!std::ranges::__concat_indirectly_readable<InnerRange, Pattern>);
287static_assert(!CanFormJoinWithView<View<InnerRange>, Pattern>);
288} // namespace not_concat_indirectly_readable
289} // namespace test_when_used_ranges_are_not_concatable
290

source code of libcxx/test/std/ranges/range.adaptors/range.join.with/range.join.with.view/constraints.compile.pass.cpp