xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.join/begin.pass.cpp (revision 6a664674990094c1b5d2e717256f08cb04485899)
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 // constexpr auto begin();
12 // constexpr auto begin() const
13 //    requires forward_range<const V> &&
14 //             is_reference_v<range_reference_t<const V>> &&
15 //             input_range<range_reference_t<const V>>;
16 
17 #include <algorithm>
18 #include <cassert>
19 #include <ranges>
20 #include <string_view>
21 
22 #include "types.h"
23 
24 struct NonSimpleParentView : std::ranges::view_base {
beginNonSimpleParentView25   ChildView* begin() { return nullptr; }
26   const ChildView* begin() const;
27   const ChildView* end() const;
28 };
29 
30 struct SimpleParentView : std::ranges::view_base {
31   const ChildView* begin() const;
32   const ChildView* end() const;
33 };
34 
35 struct ConstNotRange : std::ranges::view_base {
36   const ChildView* begin();
37   const ChildView* end();
38 };
39 static_assert(std::ranges::range<ConstNotRange>);
40 static_assert(!std::ranges::range<const ConstNotRange>);
41 
42 template <class T>
43 concept HasConstBegin = requires(const T& t) { t.begin(); };
44 
test()45 constexpr bool test() {
46   int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
47 
48   {
49     ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
50     auto jv = std::ranges::join_view(ParentView{children});
51     assert(*jv.begin() == 1111);
52   }
53 
54   {
55     CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 1),
56                                  CopyableChild(buffer[3], 0)};
57     auto jv = std::ranges::join_view(ParentView{children});
58     assert(*jv.begin() == 1111);
59   }
60 
61   // Parent is empty.
62   {
63     CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]),
64                                  CopyableChild(buffer[3])};
65     std::ranges::join_view jv(ParentView(children, 0));
66     assert(jv.begin() == jv.end());
67   }
68 
69   // Parent size is one.
70   {
71     CopyableChild children[1] = {CopyableChild(buffer[0])};
72     std::ranges::join_view jv(ParentView(children, 1));
73     assert(*jv.begin() == 1111);
74   }
75 
76   // Parent and child size is one.
77   {
78     CopyableChild children[1] = {CopyableChild(buffer[0], 1)};
79     std::ranges::join_view jv(ParentView(children, 1));
80     assert(*jv.begin() == 1111);
81   }
82 
83   // Parent size is one child is empty
84   {
85     CopyableChild children[1] = {CopyableChild(buffer[0], 0)};
86     std::ranges::join_view jv(ParentView(children, 1));
87     assert(jv.begin() == jv.end());
88   }
89 
90   // Has all empty children.
91   {
92     CopyableChild children[4] = {CopyableChild(buffer[0], 0), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0),
93                                  CopyableChild(buffer[3], 0)};
94     auto jv = std::ranges::join_view(ParentView{children});
95     assert(jv.begin() == jv.end());
96   }
97 
98   // First child is empty, others are not.
99   {
100     CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0),
101                                  CopyableChild(buffer[3], 0)};
102     auto jv = std::ranges::join_view(ParentView{children});
103     assert(*jv.begin() == 1111);
104   }
105 
106   // Last child is empty, others are not.
107   {
108     CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 4), CopyableChild(buffer[2], 4),
109                                  CopyableChild(buffer[3], 0)};
110     auto jv = std::ranges::join_view(ParentView{children});
111     assert(*jv.begin() == 1111);
112   }
113 
114   {
115     std::ranges::join_view jv(buffer);
116     assert(*jv.begin() == 1111);
117   }
118 
119   {
120     const std::ranges::join_view jv(buffer);
121     assert(*jv.begin() == 1111);
122     static_assert(HasConstBegin<decltype(jv)>);
123   }
124 
125   // !forward_range<const V>
126   {
127     std::ranges::join_view jv{ConstNotRange{}};
128     static_assert(!HasConstBegin<decltype(jv)>);
129   }
130 
131   // !is_reference_v<range_reference_t<const V>>
132   {
133     auto innerRValueRange = std::views::iota(0, 5) | std::views::transform([](int) { return ChildView{}; });
134     static_assert(!std::is_reference_v<std::ranges::range_reference_t<const decltype(innerRValueRange)>>);
135     std::ranges::join_view jv{innerRValueRange};
136     static_assert(!HasConstBegin<decltype(jv)>);
137   }
138 
139   // !simple-view<V>
140   {
141     std::ranges::join_view<NonSimpleParentView> jv;
142     static_assert(!std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>);
143   }
144 
145   // simple-view<V> && is_reference_v<range_reference_t<V>>;
146   {
147     std::ranges::join_view<SimpleParentView> jv;
148     static_assert(std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>);
149   }
150 
151   // Check stashing iterators (LWG3698: regex_iterator and join_view don't work together very well)
152   {
153     std::ranges::join_view<StashingRange> jv;
154     assert(std::ranges::equal(std::views::counted(jv.begin(), 10), std::string_view{"aababcabcd"}));
155   }
156 
157   // LWG3700: The `const begin` of the `join_view` family does not require `InnerRng` to be a range
158   {
159     std::ranges::join_view<ConstNonJoinableRange> jv;
160     static_assert(!HasConstBegin<decltype(jv)>);
161   }
162 
163   // Check example from LWG3700
164   {
165     auto r = std::views::iota(0, 5) | std::views::split(1);
166     auto s = std::views::single(r);
167     auto j = s | std::views::join;
168     auto f = j.front();
169     assert(std::ranges::equal(f, std::views::single(0)));
170   }
171 
172   return true;
173 }
174 
main(int,char **)175 int main(int, char**) {
176   test();
177   static_assert(test());
178 
179   return 0;
180 }
181