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