xref: /freebsd/contrib/llvm-project/libcxx/include/__ranges/size.h (revision ec0ea6efa1ad229d75c394c1a9b9cac33af2b1d3)
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