1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___RANGES_EMPTY_H
10 #define _LIBCPP___RANGES_EMPTY_H
11 
12 #include <__config>
13 #include <__iterator/concepts.h>
14 #include <__ranges/access.h>
15 #include <__ranges/size.h>
16 #include <__utility/forward.h>
17 #include <type_traits>
18 
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #pragma GCC system_header
21 #endif
22 
23 _LIBCPP_PUSH_MACROS
24 #include <__undef_macros>
25 
26 _LIBCPP_BEGIN_NAMESPACE_STD
27 
28 #if !defined(_LIBCPP_HAS_NO_RANGES)
29 
30 // clang-format off
31 namespace ranges {
32 // [range.prim.empty]
33 namespace __empty {
34   template <class _Tp>
35   concept __member_empty = requires(_Tp&& __t) {
36     bool(_VSTD::forward<_Tp>(__t).empty());
37   };
38 
39   template<class _Tp>
40   concept __can_invoke_size =
41     !__member_empty<_Tp> &&
42     requires(_Tp&& __t) { ranges::size(_VSTD::forward<_Tp>(__t)); };
43 
44   template <class _Tp>
45   concept __can_compare_begin_end =
46     !__member_empty<_Tp> &&
47     !__can_invoke_size<_Tp> &&
48     requires(_Tp&& __t) {
49       bool(ranges::begin(__t) == ranges::end(__t));
50       { ranges::begin(__t) } -> forward_iterator;
51     };
52 
53   struct __fn {
54     template <__member_empty _Tp>
55     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const
56         noexcept(noexcept(bool(__t.empty()))) {
57       return __t.empty();
58     }
59 
60     template <__can_invoke_size _Tp>
61     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const
62         noexcept(noexcept(ranges::size(_VSTD::forward<_Tp>(__t)))) {
63       return ranges::size(_VSTD::forward<_Tp>(__t)) == 0;
64     }
65 
66     template<__can_compare_begin_end _Tp>
67     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const
68         noexcept(noexcept(bool(ranges::begin(__t) == ranges::end(__t)))) {
69       return ranges::begin(__t) == ranges::end(__t);
70     }
71   };
72 }
73 
74 inline namespace __cpo {
75   inline constexpr auto empty = __empty::__fn{};
76 } // namespace __cpo
77 } // namespace ranges
78 // clang-format off
79 
80 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
81 
82 _LIBCPP_END_NAMESPACE_STD
83 
84 _LIBCPP_POP_MACROS
85 
86 #endif // _LIBCPP___RANGES_EMPTY_H
87