xref: /openbsd/gnu/llvm/libcxx/include/__ranges/rend.h (revision 4bdff4be)
1*4bdff4beSrobert // -*- C++ -*-
2*4bdff4beSrobert //===----------------------------------------------------------------------===//
3*4bdff4beSrobert //
4*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information.
6*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*4bdff4beSrobert //
8*4bdff4beSrobert //===----------------------------------------------------------------------===//
9*4bdff4beSrobert 
10*4bdff4beSrobert #ifndef _LIBCPP___RANGES_REND_H
11*4bdff4beSrobert #define _LIBCPP___RANGES_REND_H
12*4bdff4beSrobert 
13*4bdff4beSrobert #include <__concepts/class_or_enum.h>
14*4bdff4beSrobert #include <__concepts/same_as.h>
15*4bdff4beSrobert #include <__config>
16*4bdff4beSrobert #include <__iterator/concepts.h>
17*4bdff4beSrobert #include <__iterator/readable_traits.h>
18*4bdff4beSrobert #include <__iterator/reverse_iterator.h>
19*4bdff4beSrobert #include <__ranges/access.h>
20*4bdff4beSrobert #include <__ranges/rbegin.h>
21*4bdff4beSrobert #include <__utility/auto_cast.h>
22*4bdff4beSrobert #include <type_traits>
23*4bdff4beSrobert 
24*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25*4bdff4beSrobert #  pragma GCC system_header
26*4bdff4beSrobert #endif
27*4bdff4beSrobert 
28*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
29*4bdff4beSrobert 
30*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
31*4bdff4beSrobert 
32*4bdff4beSrobert // [range.access.rend]
33*4bdff4beSrobert 
34*4bdff4beSrobert namespace ranges {
35*4bdff4beSrobert namespace __rend {
36*4bdff4beSrobert template <class _Tp>
37*4bdff4beSrobert concept __member_rend =
38*4bdff4beSrobert   __can_borrow<_Tp> &&
39*4bdff4beSrobert   __workaround_52970<_Tp> &&
requires(_Tp && __t)40*4bdff4beSrobert   requires(_Tp&& __t) {
41*4bdff4beSrobert     ranges::rbegin(__t);
42*4bdff4beSrobert     { _LIBCPP_AUTO_CAST(__t.rend()) } -> sentinel_for<decltype(ranges::rbegin(__t))>;
43*4bdff4beSrobert   };
44*4bdff4beSrobert 
45*4bdff4beSrobert void rend(auto&) = delete;
46*4bdff4beSrobert void rend(const auto&) = delete;
47*4bdff4beSrobert 
48*4bdff4beSrobert template <class _Tp>
49*4bdff4beSrobert concept __unqualified_rend =
50*4bdff4beSrobert   !__member_rend<_Tp> &&
51*4bdff4beSrobert   __can_borrow<_Tp> &&
52*4bdff4beSrobert   __class_or_enum<remove_cvref_t<_Tp>> &&
53*4bdff4beSrobert   requires(_Tp&& __t) {
54*4bdff4beSrobert     ranges::rbegin(__t);
55*4bdff4beSrobert     { _LIBCPP_AUTO_CAST(rend(__t)) } -> sentinel_for<decltype(ranges::rbegin(__t))>;
56*4bdff4beSrobert   };
57*4bdff4beSrobert 
58*4bdff4beSrobert template <class _Tp>
59*4bdff4beSrobert concept __can_reverse =
60*4bdff4beSrobert   __can_borrow<_Tp> &&
61*4bdff4beSrobert   !__member_rend<_Tp> &&
62*4bdff4beSrobert   !__unqualified_rend<_Tp> &&
63*4bdff4beSrobert   requires(_Tp&& __t) {
64*4bdff4beSrobert     { ranges::begin(__t) } -> same_as<decltype(ranges::end(__t))>;
65*4bdff4beSrobert     { ranges::begin(__t) } -> bidirectional_iterator;
66*4bdff4beSrobert   };
67*4bdff4beSrobert 
68*4bdff4beSrobert class __fn {
69*4bdff4beSrobert public:
70*4bdff4beSrobert   template <class _Tp>
71*4bdff4beSrobert     requires __member_rend<_Tp>
operator()72*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
73*4bdff4beSrobert     noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.rend())))
74*4bdff4beSrobert   {
75*4bdff4beSrobert     return _LIBCPP_AUTO_CAST(__t.rend());
76*4bdff4beSrobert   }
77*4bdff4beSrobert 
78*4bdff4beSrobert   template <class _Tp>
79*4bdff4beSrobert     requires __unqualified_rend<_Tp>
operator()80*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
81*4bdff4beSrobert     noexcept(noexcept(_LIBCPP_AUTO_CAST(rend(__t))))
82*4bdff4beSrobert   {
83*4bdff4beSrobert     return _LIBCPP_AUTO_CAST(rend(__t));
84*4bdff4beSrobert   }
85*4bdff4beSrobert 
86*4bdff4beSrobert   template <class _Tp>
87*4bdff4beSrobert     requires __can_reverse<_Tp>
operator()88*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
89*4bdff4beSrobert     noexcept(noexcept(ranges::begin(__t)))
90*4bdff4beSrobert   {
91*4bdff4beSrobert     return std::make_reverse_iterator(ranges::begin(__t));
92*4bdff4beSrobert   }
93*4bdff4beSrobert 
94*4bdff4beSrobert   void operator()(auto&&) const = delete;
95*4bdff4beSrobert };
96*4bdff4beSrobert } // namespace __rend
97*4bdff4beSrobert 
98*4bdff4beSrobert inline namespace __cpo {
99*4bdff4beSrobert   inline constexpr auto rend = __rend::__fn{};
100*4bdff4beSrobert } // namespace __cpo
101*4bdff4beSrobert } // namespace ranges
102*4bdff4beSrobert 
103*4bdff4beSrobert // [range.access.crend]
104*4bdff4beSrobert 
105*4bdff4beSrobert namespace ranges {
106*4bdff4beSrobert namespace __crend {
107*4bdff4beSrobert struct __fn {
108*4bdff4beSrobert   template <class _Tp>
109*4bdff4beSrobert     requires is_lvalue_reference_v<_Tp&&>
110*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
111*4bdff4beSrobert   constexpr auto operator()(_Tp&& __t) const
112*4bdff4beSrobert     noexcept(noexcept(ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t))))
113*4bdff4beSrobert     -> decltype(      ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)))
114*4bdff4beSrobert     { return          ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)); }
115*4bdff4beSrobert 
116*4bdff4beSrobert   template <class _Tp>
117*4bdff4beSrobert     requires is_rvalue_reference_v<_Tp&&>
118*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
119*4bdff4beSrobert   constexpr auto operator()(_Tp&& __t) const
120*4bdff4beSrobert     noexcept(noexcept(ranges::rend(static_cast<const _Tp&&>(__t))))
121*4bdff4beSrobert     -> decltype(      ranges::rend(static_cast<const _Tp&&>(__t)))
122*4bdff4beSrobert     { return          ranges::rend(static_cast<const _Tp&&>(__t)); }
123*4bdff4beSrobert };
124*4bdff4beSrobert } // namespace __crend
125*4bdff4beSrobert 
126*4bdff4beSrobert inline namespace __cpo {
127*4bdff4beSrobert   inline constexpr auto crend = __crend::__fn{};
128*4bdff4beSrobert } // namespace __cpo
129*4bdff4beSrobert } // namespace ranges
130*4bdff4beSrobert 
131*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
132*4bdff4beSrobert 
133*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
134*4bdff4beSrobert 
135*4bdff4beSrobert #endif // _LIBCPP___RANGES_REND_H
136