1fe6060f1SDimitry Andric // -*- C++ -*- 2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric // 4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric // 8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric 10fe6060f1SDimitry Andric #ifndef _LIBCPP___RANGES_EMPTY_H 11fe6060f1SDimitry Andric #define _LIBCPP___RANGES_EMPTY_H 12fe6060f1SDimitry Andric 1304eeddc0SDimitry Andric #include <__concepts/class_or_enum.h> 14fe6060f1SDimitry Andric #include <__config> 15fe6060f1SDimitry Andric #include <__iterator/concepts.h> 16fe6060f1SDimitry Andric #include <__ranges/access.h> 17fe6060f1SDimitry Andric #include <__ranges/size.h> 18fe6060f1SDimitry Andric 19fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20fe6060f1SDimitry Andric # pragma GCC system_header 21fe6060f1SDimitry Andric #endif 22fe6060f1SDimitry Andric 23fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 24fe6060f1SDimitry Andric 2506c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 26fe6060f1SDimitry Andric 27fe6060f1SDimitry Andric // [range.prim.empty] 280eae32dcSDimitry Andric 290eae32dcSDimitry Andric namespace ranges { 30fe6060f1SDimitry Andric namespace __empty { 31fe6060f1SDimitry Andric template <class _Tp> requires(_Tp && __t)32*0fca6ea1SDimitry Andricconcept __member_empty = requires(_Tp&& __t) { bool(__t.empty()); }; 33fe6060f1SDimitry Andric 34fe6060f1SDimitry Andric template <class _Tp> 35cb14a3feSDimitry Andric concept __can_invoke_size = !__member_empty<_Tp> && requires(_Tp&& __t) { ranges::size(__t); }; 36fe6060f1SDimitry Andric 37fe6060f1SDimitry Andric template <class _Tp> 38cb14a3feSDimitry Andric concept __can_compare_begin_end = !__member_empty<_Tp> && !__can_invoke_size<_Tp> && requires(_Tp&& __t) { 39fe6060f1SDimitry Andric bool(ranges::begin(__t) == ranges::end(__t)); 40fe6060f1SDimitry Andric { ranges::begin(__t) } -> forward_iterator; 41fe6060f1SDimitry Andric }; 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric struct __fn { 44fe6060f1SDimitry Andric template <__member_empty _Tp> operator__fn45cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const noexcept(noexcept(bool(__t.empty()))) { 460eae32dcSDimitry Andric return bool(__t.empty()); 47fe6060f1SDimitry Andric } 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric template <__can_invoke_size _Tp> operator__fn50cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const noexcept(noexcept(ranges::size(__t))) { 510eae32dcSDimitry Andric return ranges::size(__t) == 0; 52fe6060f1SDimitry Andric } 53fe6060f1SDimitry Andric 54fe6060f1SDimitry Andric template <__can_compare_begin_end _Tp> operator__fn55fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const 56fe6060f1SDimitry Andric noexcept(noexcept(bool(ranges::begin(__t) == ranges::end(__t)))) { 57fe6060f1SDimitry Andric return ranges::begin(__t) == ranges::end(__t); 58fe6060f1SDimitry Andric } 59fe6060f1SDimitry Andric }; 601fd87a68SDimitry Andric } // namespace __empty 61fe6060f1SDimitry Andric 62fe6060f1SDimitry Andric inline namespace __cpo { 63fe6060f1SDimitry Andric inline constexpr auto empty = __empty::__fn{}; 64fe6060f1SDimitry Andric } // namespace __cpo 65fe6060f1SDimitry Andric } // namespace ranges 66fe6060f1SDimitry Andric 6706c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 70fe6060f1SDimitry Andric 71fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_EMPTY_H 72