xref: /llvm-project/libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp (revision d2baefae6846765eef6a6dd69d4fdf1082ce29ad)
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 // template<class R>
13 // concept viewable_range;
14 
15 #include <ranges>
16 #include <type_traits>
17 
18 #include "test_iterators.h"
19 #include "test_range.h"
20 
21 // The constraints we have in viewable_range are:
22 //  range<T>
23 //  view<remove_cvref_t<T>>
24 //  constructible_from<remove_cvref_t<T>, T>
25 //  lvalue_reference_t<T> || movable<remove_reference_t<T>>
26 //  is-initializer-list<T>
27 //
28 // We test all the relevant combinations of satisfying/not satisfying those constraints.
29 
30 // viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, lvalue-or-movable=*)
31 struct T1 { };
32 static_assert(!std::ranges::range<T1>);
33 
34 static_assert(!std::ranges::viewable_range<T1>);
35 static_assert(!std::ranges::viewable_range<T1&>);
36 static_assert(!std::ranges::viewable_range<T1&&>);
37 static_assert(!std::ranges::viewable_range<T1 const>);
38 static_assert(!std::ranges::viewable_range<T1 const&>);
39 static_assert(!std::ranges::viewable_range<T1 const&&>);
40 
41 // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=true)
42 struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base {
43   T2(T2 const&) = default;
44 };
45 static_assert(std::ranges::range<T2>);
46 static_assert(std::ranges::view<T2>);
47 static_assert(std::constructible_from<T2, T2>);
48 
49 static_assert(std::ranges::viewable_range<T2>);
50 static_assert(std::ranges::viewable_range<T2&>);
51 static_assert(std::ranges::viewable_range<T2&&>);
52 static_assert(std::ranges::viewable_range<T2 const>);
53 static_assert(std::ranges::viewable_range<T2 const&>);
54 static_assert(std::ranges::viewable_range<T2 const&&>);
55 
56 // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=false)
57 struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base {
58   T3(T3 const&) = default;
59 };
60 static_assert(std::ranges::range<T3>);
61 static_assert(std::ranges::view<T3>);
62 static_assert(std::constructible_from<T3, T3>);
63 
64 static_assert(std::ranges::viewable_range<T3>);
65 static_assert(std::ranges::viewable_range<T3&>);
66 static_assert(std::ranges::viewable_range<T3&&>);
67 static_assert(std::ranges::viewable_range<T3 const>);
68 static_assert(std::ranges::viewable_range<T3 const&>);
69 static_assert(std::ranges::viewable_range<T3 const&&>);
70 
71 // viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, lvalue-or-movable=true)
72 struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base {
73   T4(T4 const&) = delete;
74   T4(T4&&) = default;             // necessary to model view
75   T4& operator=(T4&&) = default;  // necessary to model view
76 };
77 static_assert(std::ranges::range<T4 const&>);
78 static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>);
79 static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>);
80 
81 static_assert(!std::ranges::viewable_range<T4 const&>);
82 
83 // A type that satisfies (range=true, view=true, constructible_from=false, lvalue-or-movable=false) can't be formed,
84 // because views are movable by definition
85 
86 // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=true)...
87 struct T5 : test_range<cpp20_input_iterator> { };
88 static_assert( std::ranges::range<T5>);
89 static_assert(!std::ranges::view<T5>);
90 static_assert( std::constructible_from<T5, T5>);
91 static_assert( std::movable<T5>);
92 static_assert(!std::movable<const T5>);
93 
94 static_assert( std::ranges::viewable_range<T5>); // movable
95 static_assert( std::ranges::viewable_range<T5&>); // movable
96 static_assert( std::ranges::viewable_range<T5&&>); // movable
97 static_assert(!std::ranges::viewable_range<const T5>);
98 static_assert( std::ranges::viewable_range<const T5&>); // lvalue
99 static_assert(!std::ranges::viewable_range<const T5&&>);
100 
101 // ...but not if the (non-view, lvalue-or-movable) range is an initializer_list.
102 static_assert( std::ranges::range<std::initializer_list<int>>);
103 static_assert(!std::ranges::view<std::initializer_list<int>>);
104 static_assert( std::constructible_from<std::initializer_list<int>, std::initializer_list<int>>);
105 static_assert( std::movable<std::initializer_list<int>>);
106 
107 static_assert(!std::ranges::viewable_range<std::initializer_list<int>>);
108 static_assert( std::ranges::viewable_range<std::initializer_list<int>&>);
109 static_assert(!std::ranges::viewable_range<std::initializer_list<int>&&>);
110 static_assert(!std::ranges::viewable_range<std::initializer_list<int> const>);
111 static_assert( std::ranges::viewable_range<std::initializer_list<int> const&>);
112 static_assert(!std::ranges::viewable_range<std::initializer_list<int> const&&>);
113 
114 // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=false)
115 struct T6 : test_range<cpp20_input_iterator> { T6(T6&&); T6& operator=(T6&&) = delete; };
116 static_assert( std::ranges::range<T6>);
117 static_assert(!std::ranges::view<T6>);
118 static_assert( std::constructible_from<T6, T6>);
119 static_assert(!std::movable<T6>);
120 
121 static_assert(!std::ranges::viewable_range<T6>);
122 static_assert( std::ranges::viewable_range<T6&>); // lvalue
123 static_assert(!std::ranges::viewable_range<T6&&>);
124 static_assert(!std::ranges::viewable_range<const T6>);
125 static_assert( std::ranges::viewable_range<const T6&>); // lvalue
126 static_assert(!std::ranges::viewable_range<const T6&&>);
127 
128 // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=true)
129 struct T7 : test_range<cpp20_input_iterator> {
130   T7(T7 const&) = delete;
131 };
132 static_assert(std::ranges::range<T7&>);
133 static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>);
134 static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>);
135 
136 static_assert(!std::ranges::viewable_range<T7>);
137 static_assert( std::ranges::viewable_range<T7&>);
138 static_assert(!std::ranges::viewable_range<T7&&>);
139 static_assert(!std::ranges::viewable_range<const T7>);
140 static_assert( std::ranges::viewable_range<const T7&>);
141 static_assert(!std::ranges::viewable_range<const T7&&>);
142 
143 // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=false)
144 struct T8 : test_range<cpp20_input_iterator> {
145   T8(T8 const&) = delete;
146 };
147 static_assert(std::ranges::range<T8>);
148 static_assert(!std::ranges::view<T8>);
149 static_assert(!std::constructible_from<T8, T8>);
150 
151 static_assert(!std::ranges::viewable_range<T8>);
152 static_assert( std::ranges::viewable_range<T8&>);
153 static_assert(!std::ranges::viewable_range<T8&&>);
154 static_assert(!std::ranges::viewable_range<const T8>);
155 static_assert( std::ranges::viewable_range<const T8&>);
156 static_assert(!std::ranges::viewable_range<const T8&&>);
157 
158 // Test with a few degenerate types
159 static_assert(!std::ranges::viewable_range<void>);
160 static_assert(!std::ranges::viewable_range<int>);
161 static_assert(!std::ranges::viewable_range<int (*)(char)>);
162 static_assert(!std::ranges::viewable_range<int[]>);
163 static_assert(!std::ranges::viewable_range<int[10]>);
164 static_assert(!std::ranges::viewable_range<int(&)[]>); // not a range
165 static_assert( std::ranges::viewable_range<int(&)[10]>); // OK, lvalue
166 static_assert(!std::ranges::viewable_range<int(&&)[]>);
167 static_assert(!std::ranges::viewable_range<int(&&)[10]>);
168 
169 // Test ADL-proofing.
170 struct Incomplete;
171 template<class T> struct Holder { T t; };
172 
173 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*>);
174 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&>);
175 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&&>);
176 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const>);
177 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&>);
178 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&&>);
179 
180 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*[10]>);
181 static_assert( std::ranges::viewable_range<Holder<Incomplete>*(&)[10]>);
182 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*(&&)[10]>);
183 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const[10]>);
184 static_assert( std::ranges::viewable_range<Holder<Incomplete>* const(&)[10]>);
185 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const(&&)[10]>);
186