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// constexpr auto begin();
14// constexpr auto begin() const
15// requires forward_range<const V> &&
16// forward_range<const Pattern> &&
17// is_reference_v<range_reference_t<const V>> &&
18// input_range<range_reference_t<const V>>;
19
20#include <ranges>
21
22#include <algorithm>
23#include <array>
24#include <string>
25#include <vector>
26
27#include "../types.h"
28#include "test_iterators.h"
29
30template <bool Simple>
31using MaybeSimpleForwardView = BasicView<std::vector<std::string>, ViewProperties{.simple = Simple}, forward_iterator>;
32
33template <bool Simple>
34using MaybeSimpleForwardRvalueView =
35 BasicView<RvalueVector<std::string>, ViewProperties{.simple = Simple}, forward_iterator>;
36
37template <bool Simple>
38using MaybeSimplePattern = BasicView<std::string, ViewProperties{.simple = Simple}, forward_iterator>;
39
40template <class V, class Pattern>
41concept JoinWithViewHasConstBegin = requires(const std::ranges::join_with_view<V, Pattern> jwv) {
42 { jwv.begin() } -> std::input_iterator;
43};
44
45constexpr void test_begin() {
46 using Str = std::string;
47 using Vec = std::vector<Str>;
48
49 { // `V` models simple-view
50 // `is_reference_v<InnerRng>` is true
51 // `Pattern` models simple-view
52 // `V` and `Pattern` contain some elements
53 using V = MaybeSimpleForwardView<true>;
54 using Pattern = MaybeSimplePattern<true>;
55 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"A", "B", "C"}), Pattern(Str{">>"}));
56 auto it = jwv.begin();
57 assert(std::ranges::equal(std::views::counted(it, 7), Str{"A>>B>>C"}));
58 }
59
60 { // `V` does not model simple-view
61 // `is_reference_v<InnerRng>` is true
62 // `Pattern` models simple-view
63 // `V` and `Pattern` are empty
64 using V = MaybeSimpleForwardView<false>;
65 using Pattern = MaybeSimplePattern<true>;
66 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{}), Pattern(Str{}));
67 auto it = jwv.begin();
68 assert(it == jwv.end());
69 }
70
71 { // `V` models simple-view
72 // `is_reference_v<InnerRng>` is false
73 // `Pattern` models simple-view
74 // `V` contains two elements, `Pattern` is empty
75 using V = MaybeSimpleForwardRvalueView<true>;
76 using Pattern = MaybeSimplePattern<true>;
77 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"1", "2"}), Pattern(Str{""}));
78 auto it = jwv.begin();
79 assert(*it == '1');
80 assert(*++it == '2');
81 }
82
83 { // `V` models simple-view
84 // `is_reference_v<InnerRng>` is true
85 // `Pattern` does not model simple-view
86 // `V` contains one element, `Pattern` is empty
87 using V = MaybeSimpleForwardView<true>;
88 using Pattern = MaybeSimplePattern<false>;
89 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"07"}), Pattern(Str{}));
90 auto it = jwv.begin();
91 assert(*it++ == '0');
92 assert(*it == '7');
93 }
94
95 { // `V` does not model simple-view
96 // `is_reference_v<InnerRng>` is false
97 // `Pattern` models simple-view
98 // `V` contains three elements (2nd is empty), `Pattern` is not empty
99 using V = MaybeSimpleForwardRvalueView<false>;
100 using Pattern = MaybeSimplePattern<true>;
101 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"A", "", "C"}), Pattern(Str{"--"}));
102 auto it = jwv.begin();
103 assert(std::ranges::equal(std::views::counted(it, 6), Str("A----C")));
104 }
105
106 { // `V` does not model simple-view
107 // `is_reference_v<InnerRng>` is true
108 // `Pattern` does not model simple-view
109 // `V` contains some empty elements, `Pattern` is not empty
110 using V = MaybeSimpleForwardView<false>;
111 using Pattern = MaybeSimplePattern<false>;
112 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"", "", ""}), Pattern(Str{"-"}));
113 auto it = jwv.begin();
114 assert(*it++ == '-');
115 assert(*it == '-');
116 }
117
118 { // `V` models simple-view
119 // `is_reference_v<InnerRng>` is false
120 // `Pattern` does not model simple-view
121 // `V` contains two elements, `Pattern` is not empty
122 using V = MaybeSimpleForwardRvalueView<true>;
123 using Pattern = MaybeSimplePattern<false>;
124 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"X", "Z"}), Pattern(Str{"Y"}));
125 auto it = jwv.begin();
126 assert(*it == 'X');
127 assert(*++it == 'Y');
128 assert(*++it == 'Z');
129 }
130
131 { // `V` does not model simple-view
132 // `is_reference_v<InnerRng>` is false
133 // `Pattern` does not model simple-view
134 // `V` contains two empty elements, `Pattern` is not empty
135 using V = MaybeSimpleForwardRvalueView<false>;
136 using Pattern = MaybeSimplePattern<false>;
137 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"", ""}), Pattern(Str{"?"}));
138 auto it = jwv.begin();
139 assert(*it == '?');
140 assert(++it == jwv.end());
141 }
142
143 { // `V` does not model forward range
144 // `V` contains some empty elements, `Pattern` is empty
145 using V = BasicView<Vec, ViewProperties{.common = false}, cpp20_input_iterator>;
146 using Pattern = MaybeSimplePattern<false>;
147 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"", "", ""}), Pattern(Str{""}));
148 auto it = jwv.begin();
149 assert(it == jwv.end());
150 }
151}
152
153constexpr void test_const_begin() {
154 using Vec = std::vector<std::array<int, 2>>;
155 using Pat = std::array<int, 2>;
156
157 { // `const V` models forward range
158 // `const Pattern` models forward range
159 // `is_reference_v<range_reference_t<const V>>` is true
160 // `range_reference_t<const V>` models input range
161 using V = BasicView<Vec, ViewProperties{}, forward_iterator>;
162 using Pattern = BasicView<Pat, ViewProperties{}, forward_iterator>;
163
164 const std::ranges::join_with_view<V, Pattern> jwv{V{Vec{std::array{1, 2}, std::array{3, 4}}}, Pattern{Pat{0, 0}}};
165 auto it = jwv.begin();
166 assert(std::ranges::equal(std::views::counted(it, 6), std::array{1, 2, 0, 0, 3, 4}));
167 }
168
169 // `const V` does not model forward range
170 // `const Pattern` models forward range
171 // `is_reference_v<range_reference_t<const V>>` is true
172 // `range_reference_t<const V>` models input range
173 static_assert(!JoinWithViewHasConstBegin<BasicView<Vec, ViewProperties{.common = false}, cpp20_input_iterator>,
174 BasicView<Pat, ViewProperties{}, forward_iterator>>);
175
176 // `const V` models forward range
177 // `const Pattern` does not model forward range
178 // `is_reference_v<range_reference_t<const V>>` is true
179 // `range_reference_t<const V>` models input range
180 static_assert(!JoinWithViewHasConstBegin<BasicView<Vec, ViewProperties{}, forward_iterator>,
181 BasicView<Pat, ViewProperties{.common = false}, cpp20_input_iterator>>);
182
183 // `const V` models forward range
184 // `const Pattern` models forward range
185 // `is_reference_v<range_reference_t<const V>>` is false
186 // `range_reference_t<const V>` models input range
187 static_assert(
188 !JoinWithViewHasConstBegin<BasicView<RvalueVector<std::vector<int>>, ViewProperties{}, forward_iterator>,
189 BasicView<Pat, ViewProperties{}, forward_iterator>>);
190
191 // `const V` models forward range
192 // `const Pattern` models forward range
193 // `is_reference_v<range_reference_t<const V>>` is true
194 // `range_reference_t<const V>` does not model input range
195 static_assert(!JoinWithViewHasConstBegin<
196 BasicView<std::vector<InputRangeButOutputWhenConst<int>>, ViewProperties{}, forward_iterator>,
197 BasicView<Pat, ViewProperties{}, forward_iterator>>);
198
199 // `concatable<range_reference_t<const V>, const Pattern>` is not satisfied
200 // See also LWG-4074: compatible-joinable-ranges is underconstrained
201 static_assert(!JoinWithViewHasConstBegin<BasicVectorView<int, ViewProperties{}, forward_iterator>,
202 lwg4074::PatternWithProxyConstAccess>);
203
204 // Check situation when iterators returned by `begin()` and `begin() const` are the same
205 using JWV = std::ranges::join_with_view<MaybeSimpleForwardView<true>, MaybeSimplePattern<true>>;
206 static_assert(std::same_as<std::ranges::iterator_t<JWV&>, std::ranges::iterator_t<const JWV&>>);
207}
208
209constexpr bool test() {
210 test_begin();
211 test_const_begin();
212
213 return true;
214}
215
216int main(int, char**) {
217 test();
218 static_assert(test());
219
220 return 0;
221}
222

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