xref: /netbsd-src/external/apache2/llvm/dist/libcxx/include/__ranges/size.h (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
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 <type_traits>
17 
18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19 #pragma GCC system_header
20 #endif
21 
22 _LIBCPP_PUSH_MACROS
23 #include <__undef_macros>
24 
25 _LIBCPP_BEGIN_NAMESPACE_STD
26 
27 #if !defined(_LIBCPP_HAS_NO_RANGES)
28 
29 // clang-format off
30 namespace ranges {
31 template<class>
32 inline constexpr bool disable_sized_range = false;
33 
34 // [range.prim.size]
35 namespace __size {
36   void size(auto&) = delete;
37   void size(const auto&) = delete;
38 
39   template <class _Tp>
40   concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>;
41 
42   template <class _Tp>
requires(_Tp && __t)43   concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) {
44     { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).size()) } -> __integer_like;
45   };
46 
47   template <class _Tp>
48   concept __unqualified_size =
49     __size_enabled<_Tp> &&
50     !__member_size<_Tp> &&
51     __class_or_enum<remove_cvref_t<_Tp>> &&
52     requires(_Tp&& __t) {
53       { _VSTD::__decay_copy(size(_VSTD::forward<_Tp>(__t))) } -> __integer_like;
54     };
55 
56   template <class _Tp>
57   concept __difference =
58     !__member_size<_Tp> &&
59     !__unqualified_size<_Tp> &&
60     __class_or_enum<remove_cvref_t<_Tp>> &&
61     requires(_Tp&& __t) {
62       { ranges::begin(__t) } -> forward_iterator;
63       { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(declval<_Tp>()))>;
64     };
65 
66   struct __fn {
67     template <class _Tp, size_t _Sz>
operator__fn68     [[nodiscard]] constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept {
69       return _Sz;
70     }
71 
72     template <class _Tp, size_t _Sz>
operator__fn73     [[nodiscard]] constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept {
74       return _Sz;
75     }
76 
77     template <__member_size _Tp>
operator__fn78     [[nodiscard]] constexpr __integer_like auto operator()(_Tp&& __t) const
79         noexcept(noexcept(_VSTD::forward<_Tp>(__t).size())) {
80       return _VSTD::forward<_Tp>(__t).size();
81     }
82 
83     template <__unqualified_size _Tp>
operator__fn84     [[nodiscard]] constexpr __integer_like auto operator()(_Tp&& __t) const
85         noexcept(noexcept(size(_VSTD::forward<_Tp>(__t)))) {
86       return size(_VSTD::forward<_Tp>(__t));
87     }
88 
89     template<__difference _Tp>
operator__fn90     [[nodiscard]] constexpr __integer_like auto operator()(_Tp&& __t) const
91         noexcept(noexcept(ranges::end(__t) - ranges::begin(__t))) {
92       return _VSTD::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t));
93     }
94   };
95 } // end namespace __size
96 
97 inline namespace __cpo {
98   inline constexpr auto size = __size::__fn{};
99 } // namespace __cpo
100 
101 namespace __ssize {
102   struct __fn {
103     template<class _Tp>
requires__fn104       requires requires (_Tp&& __t) { ranges::size(__t); }
operator__fn105     [[nodiscard]] constexpr integral auto operator()(_Tp&& __t) const
106         noexcept(noexcept(ranges::size(__t))) {
107       using _Signed = make_signed_t<decltype(ranges::size(__t))>;
108       if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed))
109         return static_cast<ptrdiff_t>(ranges::size(__t));
110       else
111         return static_cast<_Signed>(ranges::size(__t));
112     }
113   };
114 }
115 
116 inline namespace __cpo {
117   inline constexpr const auto ssize = __ssize::__fn{};
118 } // namespace __cpo
119 
120 } // namespace ranges
121 
122 // clang-format off
123 
124 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
125 
126 _LIBCPP_END_NAMESPACE_STD
127 
128 _LIBCPP_POP_MACROS
129 
130 #endif // _LIBCPP___RANGES_SIZE_H
131