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 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11
12 // constexpr auto begin();
13 // constexpr auto begin() const
14 // requires input_range<const V> &&
15 // is_reference_v<range_reference_t<const V>>;
16
17 #include <cassert>
18 #include <ranges>
19
20 #include "types.h"
21
22 struct NonSimpleParentView : std::ranges::view_base {
beginNonSimpleParentView23 ChildView* begin() { return nullptr; }
24 const ChildView* begin() const;
25 const ChildView* end() const;
26 };
27
28 struct SimpleParentView : std::ranges::view_base {
29 const ChildView* begin() const;
30 const ChildView* end() const;
31 };
32
33 struct ConstNotRange : std::ranges::view_base {
34 const ChildView* begin();
35 const ChildView* end();
36 };
37 static_assert(std::ranges::range<ConstNotRange>);
38 static_assert(!std::ranges::range<const ConstNotRange>);
39
40 template <class T>
41 concept HasConstBegin = requires(const T& t) { t.begin(); };
42
test()43 constexpr bool test() {
44 int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
45
46 {
47 ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
48 auto jv = std::ranges::join_view(ParentView{children});
49 assert(*jv.begin() == 1111);
50 }
51
52 {
53 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 1),
54 CopyableChild(buffer[3], 0)};
55 auto jv = std::ranges::join_view(ParentView{children});
56 assert(*jv.begin() == 1111);
57 }
58
59 // Parent is empty.
60 {
61 CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]),
62 CopyableChild(buffer[3])};
63 std::ranges::join_view jv(ParentView(children, 0));
64 assert(jv.begin() == jv.end());
65 }
66
67 // Parent size is one.
68 {
69 CopyableChild children[1] = {CopyableChild(buffer[0])};
70 std::ranges::join_view jv(ParentView(children, 1));
71 assert(*jv.begin() == 1111);
72 }
73
74 // Parent and child size is one.
75 {
76 CopyableChild children[1] = {CopyableChild(buffer[0], 1)};
77 std::ranges::join_view jv(ParentView(children, 1));
78 assert(*jv.begin() == 1111);
79 }
80
81 // Parent size is one child is empty
82 {
83 CopyableChild children[1] = {CopyableChild(buffer[0], 0)};
84 std::ranges::join_view jv(ParentView(children, 1));
85 assert(jv.begin() == jv.end());
86 }
87
88 // Has all empty children.
89 {
90 CopyableChild children[4] = {CopyableChild(buffer[0], 0), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0),
91 CopyableChild(buffer[3], 0)};
92 auto jv = std::ranges::join_view(ParentView{children});
93 assert(jv.begin() == jv.end());
94 }
95
96 // First child is empty, others are not.
97 {
98 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0),
99 CopyableChild(buffer[3], 0)};
100 auto jv = std::ranges::join_view(ParentView{children});
101 assert(*jv.begin() == 1111);
102 }
103
104 // Last child is empty, others are not.
105 {
106 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 4), CopyableChild(buffer[2], 4),
107 CopyableChild(buffer[3], 0)};
108 auto jv = std::ranges::join_view(ParentView{children});
109 assert(*jv.begin() == 1111);
110 }
111
112 {
113 std::ranges::join_view jv(buffer);
114 assert(*jv.begin() == 1111);
115 }
116
117 {
118 const std::ranges::join_view jv(buffer);
119 assert(*jv.begin() == 1111);
120 static_assert(HasConstBegin<decltype(jv)>);
121 }
122
123 // !input_range<const V>
124 {
125 std::ranges::join_view jv{ConstNotRange{}};
126 static_assert(!HasConstBegin<decltype(jv)>);
127 }
128
129 // !is_reference_v<range_reference_t<const V>>
130 {
131 auto innerRValueRange = std::views::iota(0, 5) | std::views::transform([](int) { return ChildView{}; });
132 static_assert(!std::is_reference_v<std::ranges::range_reference_t<const decltype(innerRValueRange)>>);
133 std::ranges::join_view jv{innerRValueRange};
134 static_assert(!HasConstBegin<decltype(jv)>);
135 }
136
137 // !simple-view<V>
138 {
139 std::ranges::join_view<NonSimpleParentView> jv;
140 static_assert(!std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>);
141 }
142
143 // simple-view<V> && is_reference_v<range_reference_t<V>>;
144 {
145 std::ranges::join_view<SimpleParentView> jv;
146 static_assert(std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>);
147 }
148
149 return true;
150 }
151
main(int,char **)152 int main(int, char**) {
153 test();
154 static_assert(test());
155
156 return 0;
157 }
158