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