2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___RANGES_SIZE_H
11 #define _LIBCPP___RANGES_SIZE_H
13 #include <__concepts/arithmetic.h>
14 #include <__concepts/class_or_enum.h>
16 #include <__iterator/concepts.h>
17 #include <__iterator/iterator_traits.h>
18 #include <__ranges/access.h>
19 #include <__type_traits/decay.h>
20 #include <__type_traits/make_signed.h>
21 #include <__type_traits/make_unsigned.h>
22 #include <__type_traits/remove_cvref.h>
23 #include <__utility/auto_cast.h>
24 #include <__utility/declval.h>
27 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
28 # pragma GCC system_header
31 _LIBCPP_BEGIN_NAMESPACE_STD
33 #if _LIBCPP_STD_VER >= 20
37 inline constexpr bool disable_sized_range
= false;
44 void size(auto&) = delete;
45 void size(const auto&) = delete;
48 concept __size_enabled
= !disable_sized_range
<remove_cvref_t
<_Tp
>>;
51 concept __member_size
=
52 __size_enabled
<_Tp
> &&
53 __workaround_52970
<_Tp
> &&
55 { _LIBCPP_AUTO_CAST(__t
.size()) } -> __integer_like
;
59 concept __unqualified_size
=
60 __size_enabled
<_Tp
> &&
61 !__member_size
<_Tp
> &&
62 __class_or_enum
<remove_cvref_t
<_Tp
>> &&
64 { _LIBCPP_AUTO_CAST(size(__t
)) } -> __integer_like
;
68 concept __difference
=
69 !__member_size
<_Tp
> &&
70 !__unqualified_size
<_Tp
> &&
71 __class_or_enum
<remove_cvref_t
<_Tp
>> &&
73 { ranges::begin(__t
) } -> forward_iterator
;
74 { ranges::end(__t
) } -> sized_sentinel_for
<decltype(ranges::begin(std::declval
<_Tp
>()))>;
79 // `[range.prim.size]`: the array case (for rvalues).
80 template <class _Tp
, size_t _Sz
>
81 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr size_t operator()(_Tp (&&)[_Sz
]) const noexcept
{
85 // `[range.prim.size]`: the array case (for lvalues).
86 template <class _Tp
, size_t _Sz
>
87 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr size_t operator()(_Tp (&)[_Sz
]) const noexcept
{
91 // `[range.prim.size]`: `auto(t.size())` is a valid expression.
92 template <__member_size _Tp
>
93 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr __integer_like
auto operator()(_Tp
&& __t
) const
94 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t
.size()))) {
95 return _LIBCPP_AUTO_CAST(__t
.size());
98 // `[range.prim.size]`: `auto(size(t))` is a valid expression.
99 template <__unqualified_size _Tp
>
100 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr __integer_like
auto operator()(_Tp
&& __t
) const
101 noexcept(noexcept(_LIBCPP_AUTO_CAST(size(__t
)))) {
102 return _LIBCPP_AUTO_CAST(size(__t
));
105 // [range.prim.size]: the `to-unsigned-like` case.
106 template <__difference _Tp
>
107 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __t
) const
108 noexcept(noexcept(std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
))))
109 -> decltype( std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
)))
110 { return std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
));
114 } // namespace __size
116 inline namespace __cpo
{
117 inline constexpr auto size
= __size::__fn
{};
119 } // namespace ranges
121 // [range.prim.ssize]
127 requires
requires (_Tp
&& __t
) { ranges::size(__t
); }
128 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr integral
auto operator()(_Tp
&& __t
) const
129 noexcept(noexcept(ranges::size(__t
))) {
130 using _Signed
= make_signed_t
<decltype(ranges::size(__t
))>;
131 if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed
))
132 return static_cast<ptrdiff_t>(ranges::size(__t
));
134 return static_cast<_Signed
>(ranges::size(__t
));
137 } // namespace __ssize
139 inline namespace __cpo
{
140 inline constexpr auto ssize
= __ssize::__fn
{};
142 } // namespace ranges
144 #endif // _LIBCPP_STD_VER >= 20
146 _LIBCPP_END_NAMESPACE_STD
148 #endif // _LIBCPP___RANGES_SIZE_H