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/size.h> 15 #include <type_traits> 16 17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 18 #pragma GCC system_header 19 #endif 20 21 _LIBCPP_PUSH_MACROS 22 #include <__undef_macros> 23 24 _LIBCPP_BEGIN_NAMESPACE_STD 25 26 #if !defined(_LIBCPP_HAS_NO_RANGES) 27 28 // clang-format off 29 namespace ranges { 30 // [range.prim.empty] 31 namespace __empty { 32 template <class _Tp> requires(_Tp && __t)33 concept __member_empty = requires(_Tp&& __t) { 34 bool(_VSTD::forward<_Tp>(__t).empty()); 35 }; 36 37 template<class _Tp> 38 concept __can_invoke_size = 39 !__member_empty<_Tp> && 40 requires(_Tp&& __t) { ranges::size(_VSTD::forward<_Tp>(__t)); }; 41 42 template <class _Tp> 43 concept __can_compare_begin_end = 44 !__member_empty<_Tp> && 45 !__can_invoke_size<_Tp> && 46 requires(_Tp&& __t) { 47 bool(ranges::begin(__t) == ranges::end(__t)); 48 { ranges::begin(__t) } -> forward_iterator; 49 }; 50 51 struct __fn { 52 template <__member_empty _Tp> operator__fn53 [[nodiscard]] constexpr bool operator()(_Tp&& __t) const 54 noexcept(noexcept(bool(__t.empty()))) { 55 return __t.empty(); 56 } 57 58 template <__can_invoke_size _Tp> operator__fn59 [[nodiscard]] constexpr bool operator()(_Tp&& __t) const 60 noexcept(noexcept(ranges::size(_VSTD::forward<_Tp>(__t)))) { 61 return ranges::size(_VSTD::forward<_Tp>(__t)) == 0; 62 } 63 64 template<__can_compare_begin_end _Tp> operator__fn65 [[nodiscard]] constexpr bool operator()(_Tp&& __t) const 66 noexcept(noexcept(bool(ranges::begin(__t) == ranges::end(__t)))) { 67 return ranges::begin(__t) == ranges::end(__t); 68 } 69 }; 70 } 71 72 inline namespace __cpo { 73 inline constexpr auto empty = __empty::__fn{}; 74 } // namespace __cpo 75 } // namespace ranges 76 // clang-format off 77 78 #endif // !defined(_LIBCPP_HAS_NO_RANGES) 79 80 _LIBCPP_END_NAMESPACE_STD 81 82 _LIBCPP_POP_MACROS 83 84 #endif // _LIBCPP___RANGES_EMPTY_H 85