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 bool empty() requires requires { ranges::empty(r_); }
13 // constexpr bool empty() const requires requires { ranges::empty(r_); }
14 
15 #include <ranges>
16 
17 #include <array>
18 #include <cassert>
19 #include <concepts>
20 
21 #include "test_iterators.h"
22 #include "test_macros.h"
23 
24 template <class T>
25 concept HasEmpty = requires (T t) {
26   t.empty();
27 };
28 
test()29 constexpr bool test()
30 {
31   {
32     struct ComparableIters {
33       forward_iterator<int*> begin();
34       forward_iterator<int*> end();
35     };
36     using OwningView = std::ranges::owning_view<ComparableIters>;
37     static_assert(HasEmpty<OwningView&>);
38     static_assert(HasEmpty<OwningView&&>);
39     static_assert(!HasEmpty<const OwningView&>);
40     static_assert(!HasEmpty<const OwningView&&>);
41   }
42   {
43     struct NoEmpty {
44       cpp20_input_iterator<int*> begin();
45       sentinel_wrapper<cpp20_input_iterator<int*>> end();
46     };
47     static_assert(std::ranges::range<NoEmpty&>);
48     static_assert(!std::invocable<decltype(std::ranges::empty), NoEmpty&>);
49     static_assert(!std::ranges::range<const NoEmpty&>); // no begin/end
50     static_assert(!std::invocable<decltype(std::ranges::empty), const NoEmpty&>);
51     using OwningView = std::ranges::owning_view<NoEmpty>;
52     static_assert(!HasEmpty<OwningView&>);
53     static_assert(!HasEmpty<OwningView&&>);
54     static_assert(!HasEmpty<const OwningView&>);
55     static_assert(!HasEmpty<const OwningView&&>);
56   }
57   {
58     struct EmptyMember {
59       cpp20_input_iterator<int*> begin();
60       sentinel_wrapper<cpp20_input_iterator<int*>> end();
61       bool empty() const;
62     };
63     static_assert(std::ranges::range<EmptyMember&>);
64     static_assert(std::invocable<decltype(std::ranges::empty), EmptyMember&>);
65     static_assert(!std::ranges::range<const EmptyMember&>); // no begin/end
66     static_assert(std::invocable<decltype(std::ranges::empty), const EmptyMember&>);
67     using OwningView = std::ranges::owning_view<EmptyMember>;
68     static_assert(std::ranges::range<OwningView&>);
69     static_assert(!std::ranges::range<const OwningView&>); // no begin/end
70     static_assert(HasEmpty<OwningView&>);
71     static_assert(HasEmpty<OwningView&&>);
72     static_assert(HasEmpty<const OwningView&>); // but it still has empty()
73     static_assert(HasEmpty<const OwningView&&>);
74   }
75   {
76     // Test an empty view.
77     int a[] = {1};
78     auto ov = std::ranges::owning_view(std::ranges::subrange(a, a));
79     assert(ov.empty());
80     assert(std::as_const(ov).empty());
81   }
82   {
83     // Test a non-empty view.
84     int a[] = {1};
85     auto ov = std::ranges::owning_view(std::ranges::subrange(a, a+1));
86     assert(!ov.empty());
87     assert(!std::as_const(ov).empty());
88   }
89   {
90     // Test a non-view.
91     std::array<int, 2> a = {1, 2};
92     auto ov = std::ranges::owning_view(std::move(a));
93     assert(!ov.empty());
94     assert(!std::as_const(ov).empty());
95   }
96   return true;
97 }
98 
main(int,char **)99 int main(int, char**) {
100   test();
101   static_assert(test());
102 
103   return 0;
104 }
105