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_SIZE_H 11fe6060f1SDimitry Andric #define _LIBCPP___RANGES_SIZE_H 12fe6060f1SDimitry Andric 13bdd1243dSDimitry Andric #include <__concepts/arithmetic.h> 1404eeddc0SDimitry Andric #include <__concepts/class_or_enum.h> 15fe6060f1SDimitry Andric #include <__config> 16fe6060f1SDimitry Andric #include <__iterator/concepts.h> 17fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 18fe6060f1SDimitry Andric #include <__ranges/access.h> 19bdd1243dSDimitry Andric #include <__type_traits/decay.h> 20bdd1243dSDimitry Andric #include <__type_traits/make_signed.h> 21bdd1243dSDimitry Andric #include <__type_traits/make_unsigned.h> 22bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h> 230eae32dcSDimitry Andric #include <__utility/auto_cast.h> 24bdd1243dSDimitry Andric #include <__utility/declval.h> 2561cfbce3SDimitry Andric #include <cstddef> 26fe6060f1SDimitry Andric 27fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 28fe6060f1SDimitry Andric # pragma GCC system_header 29fe6060f1SDimitry Andric #endif 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 32fe6060f1SDimitry Andric 3306c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 34fe6060f1SDimitry Andric 35fe6060f1SDimitry Andric namespace ranges { 36fe6060f1SDimitry Andric template <class> 37fe6060f1SDimitry Andric inline constexpr bool disable_sized_range = false; 381fd87a68SDimitry Andric } // namespace ranges 39fe6060f1SDimitry Andric 40fe6060f1SDimitry Andric // [range.prim.size] 410eae32dcSDimitry Andric 420eae32dcSDimitry Andric namespace ranges { 43fe6060f1SDimitry Andric namespace __size { 44*0fca6ea1SDimitry Andric void size() = delete; 45fe6060f1SDimitry Andric 46fe6060f1SDimitry Andric template <class _Tp> 47fe6060f1SDimitry Andric concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>; 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric template <class _Tp> 50*0fca6ea1SDimitry Andric concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) { 510eae32dcSDimitry Andric { _LIBCPP_AUTO_CAST(__t.size()) } -> __integer_like; 52fe6060f1SDimitry Andric }; 53fe6060f1SDimitry Andric 54fe6060f1SDimitry Andric template <class _Tp> 55fe6060f1SDimitry Andric concept __unqualified_size = 56cb14a3feSDimitry Andric __size_enabled<_Tp> && !__member_size<_Tp> && __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) { 570eae32dcSDimitry Andric { _LIBCPP_AUTO_CAST(size(__t)) } -> __integer_like; 58fe6060f1SDimitry Andric }; 59fe6060f1SDimitry Andric 60fe6060f1SDimitry Andric template <class _Tp> 61fe6060f1SDimitry Andric concept __difference = 62cb14a3feSDimitry Andric !__member_size<_Tp> && !__unqualified_size<_Tp> && __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) { 63fe6060f1SDimitry Andric { ranges::begin(__t) } -> forward_iterator; 64bdd1243dSDimitry Andric { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(std::declval<_Tp>()))>; 65fe6060f1SDimitry Andric }; 66fe6060f1SDimitry Andric 67fe6060f1SDimitry Andric struct __fn { 6881ad6265SDimitry Andric // `[range.prim.size]`: the array case (for rvalues). 69fe6060f1SDimitry Andric template <class _Tp, size_t _Sz> 70fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept { 71fe6060f1SDimitry Andric return _Sz; 72fe6060f1SDimitry Andric } 73fe6060f1SDimitry Andric 7481ad6265SDimitry Andric // `[range.prim.size]`: the array case (for lvalues). 75fe6060f1SDimitry Andric template <class _Tp, size_t _Sz> 76fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept { 77fe6060f1SDimitry Andric return _Sz; 78fe6060f1SDimitry Andric } 79fe6060f1SDimitry Andric 8081ad6265SDimitry Andric // `[range.prim.size]`: `auto(t.size())` is a valid expression. 81fe6060f1SDimitry Andric template <__member_size _Tp> 82fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const 830eae32dcSDimitry Andric noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.size()))) { 840eae32dcSDimitry Andric return _LIBCPP_AUTO_CAST(__t.size()); 85fe6060f1SDimitry Andric } 86fe6060f1SDimitry Andric 8781ad6265SDimitry Andric // `[range.prim.size]`: `auto(size(t))` is a valid expression. 88fe6060f1SDimitry Andric template <__unqualified_size _Tp> 89fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const 900eae32dcSDimitry Andric noexcept(noexcept(_LIBCPP_AUTO_CAST(size(__t)))) { 910eae32dcSDimitry Andric return _LIBCPP_AUTO_CAST(size(__t)); 92fe6060f1SDimitry Andric } 93fe6060f1SDimitry Andric 9481ad6265SDimitry Andric // [range.prim.size]: the `to-unsigned-like` case. 95fe6060f1SDimitry Andric template <__difference _Tp> 9681ad6265SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 9781ad6265SDimitry Andric noexcept(noexcept(std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t)))) 98cb14a3feSDimitry Andric -> decltype(std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t))) { 99cb14a3feSDimitry Andric return std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t)); 100fe6060f1SDimitry Andric } 101fe6060f1SDimitry Andric }; 10281ad6265SDimitry Andric 1031fd87a68SDimitry Andric } // namespace __size 104fe6060f1SDimitry Andric 105fe6060f1SDimitry Andric inline namespace __cpo { 106fe6060f1SDimitry Andric inline constexpr auto size = __size::__fn{}; 107fe6060f1SDimitry Andric } // namespace __cpo 1080eae32dcSDimitry Andric } // namespace ranges 109fe6060f1SDimitry Andric 1100eae32dcSDimitry Andric // [range.prim.ssize] 1110eae32dcSDimitry Andric 1120eae32dcSDimitry Andric namespace ranges { 113fe6060f1SDimitry Andric namespace __ssize { 114fe6060f1SDimitry Andric struct __fn { 115fe6060f1SDimitry Andric template <class _Tp> 116fe6060f1SDimitry Andric requires requires(_Tp&& __t) { ranges::size(__t); } 117fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr integral auto operator()(_Tp&& __t) const 11881ad6265SDimitry Andric noexcept(noexcept(ranges::size(__t))) { 119fe6060f1SDimitry Andric using _Signed = make_signed_t<decltype(ranges::size(__t))>; 120fe6060f1SDimitry Andric if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed)) 121fe6060f1SDimitry Andric return static_cast<ptrdiff_t>(ranges::size(__t)); 122fe6060f1SDimitry Andric else 123fe6060f1SDimitry Andric return static_cast<_Signed>(ranges::size(__t)); 124fe6060f1SDimitry Andric } 125fe6060f1SDimitry Andric }; 1261fd87a68SDimitry Andric } // namespace __ssize 127fe6060f1SDimitry Andric 128fe6060f1SDimitry Andric inline namespace __cpo { 129349cc55cSDimitry Andric inline constexpr auto ssize = __ssize::__fn{}; 130fe6060f1SDimitry Andric } // namespace __cpo 131fe6060f1SDimitry Andric } // namespace ranges 132fe6060f1SDimitry Andric 13306c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 134fe6060f1SDimitry Andric 135fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 136fe6060f1SDimitry Andric 137fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_SIZE_H 138