1df324bbaSzoecarver //===----------------------------------------------------------------------===//
2df324bbaSzoecarver //
3df324bbaSzoecarver // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4df324bbaSzoecarver // See https://llvm.org/LICENSE.txt for license information.
5df324bbaSzoecarver // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6df324bbaSzoecarver //
7df324bbaSzoecarver //===----------------------------------------------------------------------===//
8df324bbaSzoecarver 
9df324bbaSzoecarver // UNSUPPORTED: c++03, c++11, c++14, c++17
10df324bbaSzoecarver // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11df324bbaSzoecarver 
12df324bbaSzoecarver // constexpr auto begin();
13*3d3103b7SHui Xie // constexpr auto begin() const
14*3d3103b7SHui Xie //    requires input_­range<const V> &&
15*3d3103b7SHui Xie //             is_reference_v<range_reference_t<const V>>;
16df324bbaSzoecarver 
17df324bbaSzoecarver #include <cassert>
18df324bbaSzoecarver #include <ranges>
19df324bbaSzoecarver 
20df324bbaSzoecarver #include "types.h"
21df324bbaSzoecarver 
22597b90ebSHui Xie struct NonSimpleParentView : std::ranges::view_base {
beginNonSimpleParentView23597b90ebSHui Xie   ChildView* begin() { return nullptr; }
24597b90ebSHui Xie   const ChildView* begin() const;
25597b90ebSHui Xie   const ChildView* end() const;
26597b90ebSHui Xie };
27597b90ebSHui Xie 
28597b90ebSHui Xie struct SimpleParentView : std::ranges::view_base {
29597b90ebSHui Xie   const ChildView* begin() const;
30597b90ebSHui Xie   const ChildView* end() const;
31597b90ebSHui Xie };
32597b90ebSHui Xie 
33*3d3103b7SHui Xie struct ConstNotRange : std::ranges::view_base {
34*3d3103b7SHui Xie   const ChildView* begin();
35*3d3103b7SHui Xie   const ChildView* end();
36*3d3103b7SHui Xie };
37*3d3103b7SHui Xie static_assert(std::ranges::range<ConstNotRange>);
38*3d3103b7SHui Xie static_assert(!std::ranges::range<const ConstNotRange>);
39*3d3103b7SHui Xie 
40*3d3103b7SHui Xie template <class T>
41*3d3103b7SHui Xie concept HasConstBegin = requires(const T& t) { t.begin(); };
42*3d3103b7SHui Xie 
test()43df324bbaSzoecarver constexpr bool test() {
44df324bbaSzoecarver   int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
45df324bbaSzoecarver 
46df324bbaSzoecarver   {
47df324bbaSzoecarver     ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
48df324bbaSzoecarver     auto jv = std::ranges::join_view(ParentView{children});
49df324bbaSzoecarver     assert(*jv.begin() == 1111);
50df324bbaSzoecarver   }
51df324bbaSzoecarver 
52df324bbaSzoecarver   {
53*3d3103b7SHui Xie     CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 1),
54*3d3103b7SHui Xie                                  CopyableChild(buffer[3], 0)};
55df324bbaSzoecarver     auto jv = std::ranges::join_view(ParentView{children});
56df324bbaSzoecarver     assert(*jv.begin() == 1111);
57df324bbaSzoecarver   }
58*3d3103b7SHui Xie 
59df324bbaSzoecarver   // Parent is empty.
60df324bbaSzoecarver   {
61*3d3103b7SHui Xie     CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]),
62*3d3103b7SHui Xie                                  CopyableChild(buffer[3])};
63df324bbaSzoecarver     std::ranges::join_view jv(ParentView(children, 0));
64df324bbaSzoecarver     assert(jv.begin() == jv.end());
65df324bbaSzoecarver   }
66*3d3103b7SHui Xie 
67df324bbaSzoecarver   // Parent size is one.
68df324bbaSzoecarver   {
69df324bbaSzoecarver     CopyableChild children[1] = {CopyableChild(buffer[0])};
70df324bbaSzoecarver     std::ranges::join_view jv(ParentView(children, 1));
71df324bbaSzoecarver     assert(*jv.begin() == 1111);
72df324bbaSzoecarver   }
73*3d3103b7SHui Xie 
74df324bbaSzoecarver   // Parent and child size is one.
75df324bbaSzoecarver   {
76df324bbaSzoecarver     CopyableChild children[1] = {CopyableChild(buffer[0], 1)};
77df324bbaSzoecarver     std::ranges::join_view jv(ParentView(children, 1));
78df324bbaSzoecarver     assert(*jv.begin() == 1111);
79df324bbaSzoecarver   }
80*3d3103b7SHui Xie 
81df324bbaSzoecarver   // Parent size is one child is empty
82df324bbaSzoecarver   {
83df324bbaSzoecarver     CopyableChild children[1] = {CopyableChild(buffer[0], 0)};
84df324bbaSzoecarver     std::ranges::join_view jv(ParentView(children, 1));
85df324bbaSzoecarver     assert(jv.begin() == jv.end());
86df324bbaSzoecarver   }
87*3d3103b7SHui Xie 
88df324bbaSzoecarver   // Has all empty children.
89df324bbaSzoecarver   {
90*3d3103b7SHui Xie     CopyableChild children[4] = {CopyableChild(buffer[0], 0), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0),
91*3d3103b7SHui Xie                                  CopyableChild(buffer[3], 0)};
92df324bbaSzoecarver     auto jv = std::ranges::join_view(ParentView{children});
93df324bbaSzoecarver     assert(jv.begin() == jv.end());
94df324bbaSzoecarver   }
95*3d3103b7SHui Xie 
96df324bbaSzoecarver   // First child is empty, others are not.
97df324bbaSzoecarver   {
98*3d3103b7SHui Xie     CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0),
99*3d3103b7SHui Xie                                  CopyableChild(buffer[3], 0)};
100df324bbaSzoecarver     auto jv = std::ranges::join_view(ParentView{children});
101df324bbaSzoecarver     assert(*jv.begin() == 1111);
102df324bbaSzoecarver   }
103*3d3103b7SHui Xie 
104df324bbaSzoecarver   // Last child is empty, others are not.
105df324bbaSzoecarver   {
106*3d3103b7SHui Xie     CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 4), CopyableChild(buffer[2], 4),
107*3d3103b7SHui Xie                                  CopyableChild(buffer[3], 0)};
108df324bbaSzoecarver     auto jv = std::ranges::join_view(ParentView{children});
109df324bbaSzoecarver     assert(*jv.begin() == 1111);
110df324bbaSzoecarver   }
111df324bbaSzoecarver 
112df324bbaSzoecarver   {
113df324bbaSzoecarver     std::ranges::join_view jv(buffer);
114df324bbaSzoecarver     assert(*jv.begin() == 1111);
115df324bbaSzoecarver   }
116df324bbaSzoecarver 
117df324bbaSzoecarver   {
118df324bbaSzoecarver     const std::ranges::join_view jv(buffer);
119df324bbaSzoecarver     assert(*jv.begin() == 1111);
120*3d3103b7SHui Xie     static_assert(HasConstBegin<decltype(jv)>);
121*3d3103b7SHui Xie   }
122*3d3103b7SHui Xie 
123*3d3103b7SHui Xie   // !input_­range<const V>
124*3d3103b7SHui Xie   {
125*3d3103b7SHui Xie     std::ranges::join_view jv{ConstNotRange{}};
126*3d3103b7SHui Xie     static_assert(!HasConstBegin<decltype(jv)>);
127*3d3103b7SHui Xie   }
128*3d3103b7SHui Xie 
129*3d3103b7SHui Xie   // !is_reference_v<range_reference_t<const V>>
130*3d3103b7SHui Xie   {
131*3d3103b7SHui Xie     auto innerRValueRange = std::views::iota(0, 5) | std::views::transform([](int) { return ChildView{}; });
132*3d3103b7SHui Xie     static_assert(!std::is_reference_v<std::ranges::range_reference_t<const decltype(innerRValueRange)>>);
133*3d3103b7SHui Xie     std::ranges::join_view jv{innerRValueRange};
134*3d3103b7SHui Xie     static_assert(!HasConstBegin<decltype(jv)>);
135df324bbaSzoecarver   }
136df324bbaSzoecarver 
137597b90ebSHui Xie   // !simple-view<V>
138597b90ebSHui Xie   {
139597b90ebSHui Xie     std::ranges::join_view<NonSimpleParentView> jv;
140*3d3103b7SHui Xie     static_assert(!std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>);
141597b90ebSHui Xie   }
142597b90ebSHui Xie 
143597b90ebSHui Xie   // simple-view<V> && is_reference_v<range_reference_t<V>>;
144597b90ebSHui Xie   {
145597b90ebSHui Xie     std::ranges::join_view<SimpleParentView> jv;
146*3d3103b7SHui Xie     static_assert(std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>);
147597b90ebSHui Xie   }
148597b90ebSHui Xie 
149df324bbaSzoecarver   return true;
150df324bbaSzoecarver }
151df324bbaSzoecarver 
main(int,char **)152df324bbaSzoecarver int main(int, char**) {
153df324bbaSzoecarver   test();
154df324bbaSzoecarver   static_assert(test());
155df324bbaSzoecarver 
156df324bbaSzoecarver   return 0;
157df324bbaSzoecarver }
158