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 <__cstddef/ptrdiff_t.h>
17 #include <__cstddef/size_t.h>
18 #include <__iterator/concepts.h>
19 #include <__iterator/iterator_traits.h>
20 #include <__ranges/access.h>
21 #include <__type_traits/decay.h>
22 #include <__type_traits/make_signed.h>
23 #include <__type_traits/make_unsigned.h>
24 #include <__type_traits/remove_cvref.h>
25 #include <__utility/auto_cast.h>
26 #include <__utility/declval.h>
28 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
29 # pragma GCC system_header
32 _LIBCPP_BEGIN_NAMESPACE_STD
34 #if _LIBCPP_STD_VER >= 20
38 inline constexpr bool disable_sized_range
= false;
48 concept __size_enabled
= !disable_sized_range
<remove_cvref_t
<_Tp
>>;
51 concept __member_size
= __size_enabled
<_Tp
> && requires(_Tp
&& __t
) {
52 { _LIBCPP_AUTO_CAST(__t
.size()) } -> __integer_like
;
56 concept __unqualified_size
=
57 __size_enabled
<_Tp
> && !__member_size
<_Tp
> && __class_or_enum
<remove_cvref_t
<_Tp
>> && requires(_Tp
&& __t
) {
58 { _LIBCPP_AUTO_CAST(size(__t
)) } -> __integer_like
;
62 concept __difference
=
63 !__member_size
<_Tp
> && !__unqualified_size
<_Tp
> && __class_or_enum
<remove_cvref_t
<_Tp
>> && requires(_Tp
&& __t
) {
64 { ranges::begin(__t
) } -> forward_iterator
;
65 { ranges::end(__t
) } -> sized_sentinel_for
<decltype(ranges::begin(std::declval
<_Tp
>()))>;
69 // `[range.prim.size]`: the array case (for rvalues).
70 template <class _Tp
, size_t _Sz
>
71 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr size_t operator()(_Tp (&&)[_Sz
]) const noexcept
{
75 // `[range.prim.size]`: the array case (for lvalues).
76 template <class _Tp
, size_t _Sz
>
77 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr size_t operator()(_Tp (&)[_Sz
]) const noexcept
{
81 // `[range.prim.size]`: `auto(t.size())` is a valid expression.
82 template <__member_size _Tp
>
83 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr __integer_like
auto operator()(_Tp
&& __t
) const
84 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t
.size()))) {
85 return _LIBCPP_AUTO_CAST(__t
.size());
88 // `[range.prim.size]`: `auto(size(t))` is a valid expression.
89 template <__unqualified_size _Tp
>
90 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr __integer_like
auto operator()(_Tp
&& __t
) const
91 noexcept(noexcept(_LIBCPP_AUTO_CAST(size(__t
)))) {
92 return _LIBCPP_AUTO_CAST(size(__t
));
95 // [range.prim.size]: the `to-unsigned-like` case.
96 template <__difference _Tp
>
97 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __t
) const
98 noexcept(noexcept(std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
))))
99 -> decltype(std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
))) {
100 return std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
));
104 } // namespace __size
106 inline namespace __cpo
{
107 inline constexpr auto size
= __size::__fn
{};
109 } // namespace ranges
111 // [range.prim.ssize]
117 requires
requires(_Tp
&& __t
) { ranges::size(__t
); }
118 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr integral
auto operator()(_Tp
&& __t
) const
119 noexcept(noexcept(ranges::size(__t
))) {
120 using _Signed
= make_signed_t
<decltype(ranges::size(__t
))>;
121 if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed
))
122 return static_cast<ptrdiff_t>(ranges::size(__t
));
124 return static_cast<_Signed
>(ranges::size(__t
));
127 } // namespace __ssize
129 inline namespace __cpo
{
130 inline constexpr auto ssize
= __ssize::__fn
{};
132 } // namespace ranges
134 #endif // _LIBCPP_STD_VER >= 20
136 _LIBCPP_END_NAMESPACE_STD
138 #endif // _LIBCPP___RANGES_SIZE_H