xref: /aosp_15_r20/external/cronet/third_party/libc++/src/test/std/ranges/range.access/empty.pass.cpp (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 // std::ranges::empty
12 
13 #include <ranges>
14 
15 #include <cassert>
16 #include <utility>
17 #include "test_macros.h"
18 #include "test_iterators.h"
19 
20 using RangeEmptyT = decltype(std::ranges::empty);
21 
22 static_assert(!std::is_invocable_v<RangeEmptyT, int[]>);
23 static_assert(!std::is_invocable_v<RangeEmptyT, int(&)[]>);
24 static_assert(!std::is_invocable_v<RangeEmptyT, int(&&)[]>);
25 static_assert( std::is_invocable_v<RangeEmptyT, int[1]>);
26 static_assert( std::is_invocable_v<RangeEmptyT, const int[1]>);
27 static_assert( std::is_invocable_v<RangeEmptyT, int (&&)[1]>);
28 static_assert( std::is_invocable_v<RangeEmptyT, int (&)[1]>);
29 static_assert( std::is_invocable_v<RangeEmptyT, const int (&)[1]>);
30 
31 struct Incomplete;
32 static_assert(!std::is_invocable_v<RangeEmptyT, Incomplete[]>);
33 static_assert(!std::is_invocable_v<RangeEmptyT, Incomplete(&)[]>);
34 static_assert(!std::is_invocable_v<RangeEmptyT, Incomplete(&&)[]>);
35 
36 extern Incomplete array_of_incomplete[42];
37 static_assert(!std::ranges::empty(array_of_incomplete));
38 static_assert(!std::ranges::empty(std::move(array_of_incomplete)));
39 static_assert(!std::ranges::empty(std::as_const(array_of_incomplete)));
40 static_assert(!std::ranges::empty(static_cast<const Incomplete(&&)[42]>(array_of_incomplete)));
41 
42 struct InputRangeWithoutSize {
43     cpp17_input_iterator<int*> begin() const;
44     cpp17_input_iterator<int*> end() const;
45 };
46 static_assert(!std::is_invocable_v<RangeEmptyT, const InputRangeWithoutSize&>);
47 
48 struct NonConstEmpty {
49   bool empty();
50 };
51 static_assert(!std::is_invocable_v<RangeEmptyT, const NonConstEmpty&>);
52 
53 struct HasMemberAndFunction {
emptyHasMemberAndFunction54   constexpr bool empty() const { return true; }
55   // We should never do ADL lookup for std::ranges::empty.
empty(const HasMemberAndFunction &)56   friend bool empty(const HasMemberAndFunction&) { return false; }
57 };
58 
59 struct BadReturnType {
emptyBadReturnType60   BadReturnType empty() { return {}; }
61 };
62 static_assert(!std::is_invocable_v<RangeEmptyT, BadReturnType&>);
63 
64 struct BoolConvertible {
operator boolBoolConvertible65   constexpr explicit operator bool() noexcept(false) { return true; }
66 };
67 struct BoolConvertibleReturnType {
emptyBoolConvertibleReturnType68   constexpr BoolConvertible empty() noexcept { return {}; }
69 };
70 static_assert(!noexcept(std::ranges::empty(BoolConvertibleReturnType())));
71 
72 struct InputIterators {
73   cpp17_input_iterator<int*> begin() const;
74   cpp17_input_iterator<int*> end() const;
75 };
76 static_assert(std::is_same_v<decltype(InputIterators().begin() == InputIterators().end()), bool>);
77 static_assert(!std::is_invocable_v<RangeEmptyT, const InputIterators&>);
78 
testEmptyMember()79 constexpr bool testEmptyMember() {
80   HasMemberAndFunction a;
81   assert(std::ranges::empty(a));
82 
83   BoolConvertibleReturnType b;
84   assert(std::ranges::empty(b));
85 
86   return true;
87 }
88 
89 struct SizeMember {
90   std::size_t size_;
sizeSizeMember91   constexpr std::size_t size() const { return size_; }
92 };
93 
94 struct SizeFunction {
95   std::size_t size_;
size(SizeFunction sf)96   friend constexpr std::size_t size(SizeFunction sf) { return sf.size_; }
97 };
98 
99 struct BeginEndSizedSentinel {
beginBeginEndSizedSentinel100   constexpr int *begin() const { return nullptr; }
endBeginEndSizedSentinel101   constexpr auto end() const { return sized_sentinel<int*>(nullptr); }
102 };
103 static_assert(std::ranges::forward_range<BeginEndSizedSentinel>);
104 static_assert(std::ranges::sized_range<BeginEndSizedSentinel>);
105 
testUsingRangesSize()106 constexpr bool testUsingRangesSize() {
107   SizeMember a{1};
108   assert(!std::ranges::empty(a));
109   SizeMember b{0};
110   assert(std::ranges::empty(b));
111 
112   SizeFunction c{1};
113   assert(!std::ranges::empty(c));
114   SizeFunction d{0};
115   assert(std::ranges::empty(d));
116 
117   BeginEndSizedSentinel e;
118   assert(std::ranges::empty(e));
119 
120   return true;
121 }
122 
123 struct BeginEndNotSizedSentinel {
beginBeginEndNotSizedSentinel124   constexpr int *begin() const { return nullptr; }
endBeginEndNotSizedSentinel125   constexpr auto end() const { return sentinel_wrapper<int*>(nullptr); }
126 };
127 static_assert( std::ranges::forward_range<BeginEndNotSizedSentinel>);
128 static_assert(!std::ranges::sized_range<BeginEndNotSizedSentinel>);
129 
130 // size is disabled here, so we have to compare begin and end.
131 struct DisabledSizeRangeWithBeginEnd {
beginDisabledSizeRangeWithBeginEnd132   constexpr int *begin() const { return nullptr; }
endDisabledSizeRangeWithBeginEnd133   constexpr auto end() const { return sentinel_wrapper<int*>(nullptr); }
134   std::size_t size() const;
135 };
136 template<>
137 inline constexpr bool std::ranges::disable_sized_range<DisabledSizeRangeWithBeginEnd> = true;
138 static_assert(std::ranges::contiguous_range<DisabledSizeRangeWithBeginEnd>);
139 static_assert(!std::ranges::sized_range<DisabledSizeRangeWithBeginEnd>);
140 
141 struct BeginEndAndEmpty {
beginBeginEndAndEmpty142   constexpr int *begin() const { return nullptr; }
endBeginEndAndEmpty143   constexpr auto end() const { return sentinel_wrapper<int*>(nullptr); }
emptyBeginEndAndEmpty144   constexpr bool empty() { return false; }
145 };
146 
147 struct EvilBeginEnd {
148   bool empty() &&;
beginEvilBeginEnd149   constexpr int *begin() & { return nullptr; }
endEvilBeginEnd150   constexpr int *end() & { return nullptr; }
151 };
152 
testBeginEqualsEnd()153 constexpr bool testBeginEqualsEnd() {
154   BeginEndNotSizedSentinel a;
155   assert(std::ranges::empty(a));
156 
157   DisabledSizeRangeWithBeginEnd d;
158   assert(std::ranges::empty(d));
159 
160   BeginEndAndEmpty e;
161   assert(!std::ranges::empty(e)); // e.empty()
162   assert(std::ranges::empty(std::as_const(e))); // e.begin() == e.end()
163 
164   assert(std::ranges::empty(EvilBeginEnd()));
165 
166   return true;
167 }
168 
169 // Test ADL-proofing.
170 struct Incomplete;
171 template<class T> struct Holder { T t; };
172 static_assert(!std::is_invocable_v<RangeEmptyT, Holder<Incomplete>*>);
173 static_assert(!std::is_invocable_v<RangeEmptyT, Holder<Incomplete>*&>);
174 
main(int,char **)175 int main(int, char**) {
176   testEmptyMember();
177   static_assert(testEmptyMember());
178 
179   testUsingRangesSize();
180   static_assert(testUsingRangesSize());
181 
182   testBeginEqualsEnd();
183   static_assert(testBeginEqualsEnd());
184 
185   return 0;
186 }
187