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