blob: 7ee574ccfa6745f18324d4c79ab32a656f5574c6 [file] [log] [blame]
Yi Kong83283012023-12-13 12:57:00 +09001// -*- 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
10#ifndef _LIBCPP___RANGES_REND_H
11#define _LIBCPP___RANGES_REND_H
12
13#include <__concepts/class_or_enum.h>
14#include <__concepts/same_as.h>
15#include <__config>
16#include <__iterator/concepts.h>
17#include <__iterator/readable_traits.h>
18#include <__iterator/reverse_iterator.h>
19#include <__ranges/access.h>
20#include <__ranges/rbegin.h>
21#include <__type_traits/decay.h>
22#include <__type_traits/is_reference.h>
23#include <__type_traits/remove_cvref.h>
24#include <__type_traits/remove_reference.h>
25#include <__utility/auto_cast.h>
26
27#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
28# pragma GCC system_header
29#endif
30
31_LIBCPP_BEGIN_NAMESPACE_STD
32
33#if _LIBCPP_STD_VER >= 20
34
35// [range.access.rend]
36
37namespace ranges {
38namespace __rend {
39template <class _Tp>
40concept __member_rend =
41 __can_borrow<_Tp> &&
42 __workaround_52970<_Tp> &&
43 requires(_Tp&& __t) {
44 ranges::rbegin(__t);
45 { _LIBCPP_AUTO_CAST(__t.rend()) } -> sentinel_for<decltype(ranges::rbegin(__t))>;
46 };
47
48void rend(auto&) = delete;
49void rend(const auto&) = delete;
50
51template <class _Tp>
52concept __unqualified_rend =
53 !__member_rend<_Tp> &&
54 __can_borrow<_Tp> &&
55 __class_or_enum<remove_cvref_t<_Tp>> &&
56 requires(_Tp&& __t) {
57 ranges::rbegin(__t);
58 { _LIBCPP_AUTO_CAST(rend(__t)) } -> sentinel_for<decltype(ranges::rbegin(__t))>;
59 };
60
61template <class _Tp>
62concept __can_reverse =
63 __can_borrow<_Tp> &&
64 !__member_rend<_Tp> &&
65 !__unqualified_rend<_Tp> &&
66 requires(_Tp&& __t) {
67 { ranges::begin(__t) } -> same_as<decltype(ranges::end(__t))>;
68 { ranges::begin(__t) } -> bidirectional_iterator;
69 };
70
71class __fn {
72public:
73 template <class _Tp>
74 requires __member_rend<_Tp>
75 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
76 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.rend())))
77 {
78 return _LIBCPP_AUTO_CAST(__t.rend());
79 }
80
81 template <class _Tp>
82 requires __unqualified_rend<_Tp>
83 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
84 noexcept(noexcept(_LIBCPP_AUTO_CAST(rend(__t))))
85 {
86 return _LIBCPP_AUTO_CAST(rend(__t));
87 }
88
89 template <class _Tp>
90 requires __can_reverse<_Tp>
91 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
92 noexcept(noexcept(ranges::begin(__t)))
93 {
94 return std::make_reverse_iterator(ranges::begin(__t));
95 }
96
97 void operator()(auto&&) const = delete;
98};
99} // namespace __rend
100
101inline namespace __cpo {
102 inline constexpr auto rend = __rend::__fn{};
103} // namespace __cpo
104} // namespace ranges
105
106// [range.access.crend]
107
108namespace ranges {
109namespace __crend {
110struct __fn {
111 template <class _Tp>
112 requires is_lvalue_reference_v<_Tp&&>
113 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
114 constexpr auto operator()(_Tp&& __t) const
115 noexcept(noexcept(ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t))))
116 -> decltype( ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)))
117 { return ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)); }
118
119 template <class _Tp>
120 requires is_rvalue_reference_v<_Tp&&>
121 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
122 constexpr auto operator()(_Tp&& __t) const
123 noexcept(noexcept(ranges::rend(static_cast<const _Tp&&>(__t))))
124 -> decltype( ranges::rend(static_cast<const _Tp&&>(__t)))
125 { return ranges::rend(static_cast<const _Tp&&>(__t)); }
126};
127} // namespace __crend
128
129inline namespace __cpo {
130 inline constexpr auto crend = __crend::__fn{};
131} // namespace __cpo
132} // namespace ranges
133
134#endif // _LIBCPP_STD_VER >= 20
135
136_LIBCPP_END_NAMESPACE_STD
137
138#endif // _LIBCPP___RANGES_REND_H