xref: /openbsd-src/gnu/llvm/libcxx/include/__ranges/size.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
176d0caaeSpatrick // -*- C++ -*-
276d0caaeSpatrick //===----------------------------------------------------------------------===//
376d0caaeSpatrick //
476d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
576d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information.
676d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
776d0caaeSpatrick //
876d0caaeSpatrick //===----------------------------------------------------------------------===//
9*4bdff4beSrobert 
1076d0caaeSpatrick #ifndef _LIBCPP___RANGES_SIZE_H
1176d0caaeSpatrick #define _LIBCPP___RANGES_SIZE_H
1276d0caaeSpatrick 
13*4bdff4beSrobert #include <__concepts/arithmetic.h>
14*4bdff4beSrobert #include <__concepts/class_or_enum.h>
1576d0caaeSpatrick #include <__config>
1676d0caaeSpatrick #include <__iterator/concepts.h>
1776d0caaeSpatrick #include <__iterator/iterator_traits.h>
1876d0caaeSpatrick #include <__ranges/access.h>
19*4bdff4beSrobert #include <__type_traits/decay.h>
20*4bdff4beSrobert #include <__type_traits/make_signed.h>
21*4bdff4beSrobert #include <__type_traits/make_unsigned.h>
22*4bdff4beSrobert #include <__type_traits/remove_cvref.h>
23*4bdff4beSrobert #include <__utility/auto_cast.h>
24*4bdff4beSrobert #include <__utility/declval.h>
25*4bdff4beSrobert #include <cstddef>
2676d0caaeSpatrick 
2776d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2876d0caaeSpatrick #  pragma GCC system_header
2976d0caaeSpatrick #endif
3076d0caaeSpatrick 
3176d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD
3276d0caaeSpatrick 
33*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
3476d0caaeSpatrick 
3576d0caaeSpatrick namespace ranges {
3676d0caaeSpatrick   template<class>
3776d0caaeSpatrick   inline constexpr bool disable_sized_range = false;
38*4bdff4beSrobert } // namespace ranges
3976d0caaeSpatrick 
4076d0caaeSpatrick // [range.prim.size]
41*4bdff4beSrobert 
42*4bdff4beSrobert namespace ranges {
4376d0caaeSpatrick namespace __size {
4476d0caaeSpatrick void size(auto&) = delete;
4576d0caaeSpatrick void size(const auto&) = delete;
4676d0caaeSpatrick 
4776d0caaeSpatrick template <class _Tp>
4876d0caaeSpatrick concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>;
4976d0caaeSpatrick 
5076d0caaeSpatrick template <class _Tp>
51*4bdff4beSrobert concept __member_size =
52*4bdff4beSrobert   __size_enabled<_Tp> &&
53*4bdff4beSrobert   __workaround_52970<_Tp> &&
requires(_Tp && __t)54*4bdff4beSrobert   requires(_Tp&& __t) {
55*4bdff4beSrobert     { _LIBCPP_AUTO_CAST(__t.size()) } -> __integer_like;
5676d0caaeSpatrick   };
5776d0caaeSpatrick 
5876d0caaeSpatrick template <class _Tp>
5976d0caaeSpatrick concept __unqualified_size =
6076d0caaeSpatrick   __size_enabled<_Tp> &&
6176d0caaeSpatrick   !__member_size<_Tp> &&
6276d0caaeSpatrick   __class_or_enum<remove_cvref_t<_Tp>> &&
6376d0caaeSpatrick   requires(_Tp&& __t) {
64*4bdff4beSrobert     { _LIBCPP_AUTO_CAST(size(__t)) } -> __integer_like;
6576d0caaeSpatrick   };
6676d0caaeSpatrick 
6776d0caaeSpatrick template <class _Tp>
6876d0caaeSpatrick concept __difference =
6976d0caaeSpatrick   !__member_size<_Tp> &&
7076d0caaeSpatrick   !__unqualified_size<_Tp> &&
7176d0caaeSpatrick   __class_or_enum<remove_cvref_t<_Tp>> &&
7276d0caaeSpatrick   requires(_Tp&& __t) {
7376d0caaeSpatrick     { ranges::begin(__t) } -> forward_iterator;
74*4bdff4beSrobert     { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(std::declval<_Tp>()))>;
7576d0caaeSpatrick   };
7676d0caaeSpatrick 
7776d0caaeSpatrick struct __fn {
78*4bdff4beSrobert 
79*4bdff4beSrobert   // `[range.prim.size]`: the array case (for rvalues).
8076d0caaeSpatrick   template <class _Tp, size_t _Sz>
operator__fn8176d0caaeSpatrick   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept {
8276d0caaeSpatrick     return _Sz;
8376d0caaeSpatrick   }
8476d0caaeSpatrick 
85*4bdff4beSrobert   // `[range.prim.size]`: the array case (for lvalues).
8676d0caaeSpatrick   template <class _Tp, size_t _Sz>
operator__fn8776d0caaeSpatrick   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept {
8876d0caaeSpatrick     return _Sz;
8976d0caaeSpatrick   }
9076d0caaeSpatrick 
91*4bdff4beSrobert   // `[range.prim.size]`: `auto(t.size())` is a valid expression.
9276d0caaeSpatrick   template <__member_size _Tp>
operator__fn9376d0caaeSpatrick   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
94*4bdff4beSrobert       noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.size()))) {
95*4bdff4beSrobert     return _LIBCPP_AUTO_CAST(__t.size());
9676d0caaeSpatrick   }
9776d0caaeSpatrick 
98*4bdff4beSrobert   // `[range.prim.size]`: `auto(size(t))` is a valid expression.
9976d0caaeSpatrick   template <__unqualified_size _Tp>
operator__fn10076d0caaeSpatrick   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
101*4bdff4beSrobert       noexcept(noexcept(_LIBCPP_AUTO_CAST(size(__t)))) {
102*4bdff4beSrobert     return _LIBCPP_AUTO_CAST(size(__t));
10376d0caaeSpatrick   }
10476d0caaeSpatrick 
105*4bdff4beSrobert   // [range.prim.size]: the `to-unsigned-like` case.
10676d0caaeSpatrick   template <__difference _Tp>
107*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
108*4bdff4beSrobert     noexcept(noexcept(std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t))))
109*4bdff4beSrobert     -> decltype(      std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t)))
110*4bdff4beSrobert     { return          std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t));
11176d0caaeSpatrick   }
11276d0caaeSpatrick };
113*4bdff4beSrobert 
114*4bdff4beSrobert } // namespace __size
11576d0caaeSpatrick 
11676d0caaeSpatrick inline namespace __cpo {
11776d0caaeSpatrick   inline constexpr auto size = __size::__fn{};
11876d0caaeSpatrick } // namespace __cpo
119*4bdff4beSrobert } // namespace ranges
12076d0caaeSpatrick 
121*4bdff4beSrobert // [range.prim.ssize]
122*4bdff4beSrobert 
123*4bdff4beSrobert namespace ranges {
12476d0caaeSpatrick namespace __ssize {
12576d0caaeSpatrick struct __fn {
12676d0caaeSpatrick   template<class _Tp>
requires__fn12776d0caaeSpatrick     requires requires (_Tp&& __t) { ranges::size(__t); }
operator__fn12876d0caaeSpatrick   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr integral auto operator()(_Tp&& __t) const
12976d0caaeSpatrick     noexcept(noexcept(ranges::size(__t))) {
13076d0caaeSpatrick     using _Signed = make_signed_t<decltype(ranges::size(__t))>;
13176d0caaeSpatrick     if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed))
13276d0caaeSpatrick       return static_cast<ptrdiff_t>(ranges::size(__t));
13376d0caaeSpatrick     else
13476d0caaeSpatrick       return static_cast<_Signed>(ranges::size(__t));
13576d0caaeSpatrick   }
13676d0caaeSpatrick };
137*4bdff4beSrobert } // namespace __ssize
13876d0caaeSpatrick 
13976d0caaeSpatrick inline namespace __cpo {
140*4bdff4beSrobert   inline constexpr auto ssize = __ssize::__fn{};
14176d0caaeSpatrick } // namespace __cpo
14276d0caaeSpatrick } // namespace ranges
14376d0caaeSpatrick 
144*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
14576d0caaeSpatrick 
14676d0caaeSpatrick _LIBCPP_END_NAMESPACE_STD
14776d0caaeSpatrick 
14876d0caaeSpatrick #endif // _LIBCPP___RANGES_SIZE_H
149