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;
47 concept __size_enabled
= !disable_sized_range
<remove_cvref_t
<_Tp
>>;
50 concept __member_size
= __size_enabled
<_Tp
> && requires(_Tp
&& __t
) {
51 { _LIBCPP_AUTO_CAST(__t
.size()) } -> __integer_like
;
55 concept __unqualified_size
=
56 __size_enabled
<_Tp
> && !__member_size
<_Tp
> && __class_or_enum
<remove_cvref_t
<_Tp
>> && requires(_Tp
&& __t
) {
57 { _LIBCPP_AUTO_CAST(size(__t
)) } -> __integer_like
;
61 concept __difference
=
62 !__member_size
<_Tp
> && !__unqualified_size
<_Tp
> && __class_or_enum
<remove_cvref_t
<_Tp
>> && requires(_Tp
&& __t
) {
63 { ranges::begin(__t
) } -> forward_iterator
;
64 { ranges::end(__t
) } -> sized_sentinel_for
<decltype(ranges::begin(std::declval
<_Tp
>()))>;
68 // `[range.prim.size]`: the array case (for rvalues).
69 template <class _Tp
, size_t _Sz
>
70 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr size_t operator()(_Tp (&&)[_Sz
]) const noexcept
{
74 // `[range.prim.size]`: the array case (for lvalues).
75 template <class _Tp
, size_t _Sz
>
76 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr size_t operator()(_Tp (&)[_Sz
]) const noexcept
{
80 // `[range.prim.size]`: `auto(t.size())` is a valid expression.
81 template <__member_size _Tp
>
82 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr __integer_like
auto operator()(_Tp
&& __t
) const
83 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t
.size()))) {
84 return _LIBCPP_AUTO_CAST(__t
.size());
87 // `[range.prim.size]`: `auto(size(t))` is a valid expression.
88 template <__unqualified_size _Tp
>
89 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr __integer_like
auto operator()(_Tp
&& __t
) const
90 noexcept(noexcept(_LIBCPP_AUTO_CAST(size(__t
)))) {
91 return _LIBCPP_AUTO_CAST(size(__t
));
94 // [range.prim.size]: the `to-unsigned-like` case.
95 template <__difference _Tp
>
96 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __t
) const
97 noexcept(noexcept(std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
))))
98 -> decltype(std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
))) {
99 return std::__to_unsigned_like(ranges::end(__t
) - ranges::begin(__t
));
103 } // namespace __size
105 inline namespace __cpo
{
106 inline constexpr auto size
= __size::__fn
{};
108 } // namespace ranges
110 // [range.prim.ssize]
116 requires
requires(_Tp
&& __t
) { ranges::size(__t
); }
117 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr integral
auto operator()(_Tp
&& __t
) const
118 noexcept(noexcept(ranges::size(__t
))) {
119 using _Signed
= make_signed_t
<decltype(ranges::size(__t
))>;
120 if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed
))
121 return static_cast<ptrdiff_t>(ranges::size(__t
));
123 return static_cast<_Signed
>(ranges::size(__t
));
126 } // namespace __ssize
128 inline namespace __cpo
{
129 inline constexpr auto ssize
= __ssize::__fn
{};
131 } // namespace ranges
133 #endif // _LIBCPP_STD_VER >= 20
135 _LIBCPP_END_NAMESPACE_STD
137 #endif // _LIBCPP___RANGES_SIZE_H