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_SIZE_H 10 #define _LIBCPP___RANGES_SIZE_H 11 12 #include <__config> 13 #include <__iterator/concepts.h> 14 #include <__iterator/iterator_traits.h> 15 #include <__ranges/access.h> 16 #include <__utility/__decay_copy.h> 17 #include <__utility/forward.h> 18 #include <concepts> 19 #include <type_traits> 20 21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 22 #pragma GCC system_header 23 #endif 24 25 _LIBCPP_PUSH_MACROS 26 #include <__undef_macros> 27 28 _LIBCPP_BEGIN_NAMESPACE_STD 29 30 #if !defined(_LIBCPP_HAS_NO_RANGES) 31 32 // clang-format off 33 namespace ranges { 34 template<class> 35 inline constexpr bool disable_sized_range = false; 36 37 // [range.prim.size] 38 namespace __size { 39 void size(auto&) = delete; 40 void size(const auto&) = delete; 41 42 template <class _Tp> 43 concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>; 44 45 template <class _Tp> 46 concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) { 47 { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).size()) } -> __integer_like; 48 }; 49 50 template <class _Tp> 51 concept __unqualified_size = 52 __size_enabled<_Tp> && 53 !__member_size<_Tp> && 54 __class_or_enum<remove_cvref_t<_Tp>> && 55 requires(_Tp&& __t) { 56 { _VSTD::__decay_copy(size(_VSTD::forward<_Tp>(__t))) } -> __integer_like; 57 }; 58 59 template <class _Tp> 60 concept __difference = 61 !__member_size<_Tp> && 62 !__unqualified_size<_Tp> && 63 __class_or_enum<remove_cvref_t<_Tp>> && 64 requires(_Tp&& __t) { 65 { ranges::begin(__t) } -> forward_iterator; 66 { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(declval<_Tp>()))>; 67 }; 68 69 struct __fn { 70 template <class _Tp, size_t _Sz> 71 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept { 72 return _Sz; 73 } 74 75 template <class _Tp, size_t _Sz> 76 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept { 77 return _Sz; 78 } 79 80 template <__member_size _Tp> 81 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const 82 noexcept(noexcept(_VSTD::forward<_Tp>(__t).size())) { 83 return _VSTD::forward<_Tp>(__t).size(); 84 } 85 86 template <__unqualified_size _Tp> 87 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const 88 noexcept(noexcept(size(_VSTD::forward<_Tp>(__t)))) { 89 return size(_VSTD::forward<_Tp>(__t)); 90 } 91 92 template<__difference _Tp> 93 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const 94 noexcept(noexcept(ranges::end(__t) - ranges::begin(__t))) { 95 return _VSTD::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t)); 96 } 97 }; 98 } // end namespace __size 99 100 inline namespace __cpo { 101 inline constexpr auto size = __size::__fn{}; 102 } // namespace __cpo 103 104 namespace __ssize { 105 struct __fn { 106 template<class _Tp> 107 requires requires (_Tp&& __t) { ranges::size(__t); } 108 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr integral auto operator()(_Tp&& __t) const 109 noexcept(noexcept(ranges::size(__t))) { 110 using _Signed = make_signed_t<decltype(ranges::size(__t))>; 111 if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed)) 112 return static_cast<ptrdiff_t>(ranges::size(__t)); 113 else 114 return static_cast<_Signed>(ranges::size(__t)); 115 } 116 }; 117 } 118 119 inline namespace __cpo { 120 inline constexpr const auto ssize = __ssize::__fn{}; 121 } // namespace __cpo 122 } // namespace ranges 123 124 // clang-format off 125 126 #endif // !defined(_LIBCPP_HAS_NO_RANGES) 127 128 _LIBCPP_END_NAMESPACE_STD 129 130 _LIBCPP_POP_MACROS 131 132 #endif // _LIBCPP___RANGES_SIZE_H 133