xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ranges/reverse_view.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1349cc55cSDimitry Andric // -*- C++ -*-
2349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
3349cc55cSDimitry Andric //
4349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7349cc55cSDimitry Andric //
8349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
9bdd1243dSDimitry Andric 
10349cc55cSDimitry Andric #ifndef _LIBCPP___RANGES_REVERSE_VIEW_H
11349cc55cSDimitry Andric #define _LIBCPP___RANGES_REVERSE_VIEW_H
12349cc55cSDimitry Andric 
13349cc55cSDimitry Andric #include <__concepts/constructible.h>
14349cc55cSDimitry Andric #include <__config>
15349cc55cSDimitry Andric #include <__iterator/concepts.h>
16349cc55cSDimitry Andric #include <__iterator/next.h>
17349cc55cSDimitry Andric #include <__iterator/reverse_iterator.h>
18349cc55cSDimitry Andric #include <__ranges/access.h>
19349cc55cSDimitry Andric #include <__ranges/all.h>
20349cc55cSDimitry Andric #include <__ranges/concepts.h>
21349cc55cSDimitry Andric #include <__ranges/enable_borrowed_range.h>
22349cc55cSDimitry Andric #include <__ranges/non_propagating_cache.h>
23349cc55cSDimitry Andric #include <__ranges/range_adaptor.h>
24349cc55cSDimitry Andric #include <__ranges/size.h>
25349cc55cSDimitry Andric #include <__ranges/subrange.h>
26349cc55cSDimitry Andric #include <__ranges/view_interface.h>
2706c3fb27SDimitry Andric #include <__type_traits/conditional.h>
2806c3fb27SDimitry Andric #include <__type_traits/remove_cvref.h>
29349cc55cSDimitry Andric #include <__utility/forward.h>
30349cc55cSDimitry Andric #include <__utility/move.h>
31349cc55cSDimitry Andric 
32349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
33349cc55cSDimitry Andric #  pragma GCC system_header
34349cc55cSDimitry Andric #endif
35349cc55cSDimitry Andric 
36b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS
37b3edf446SDimitry Andric #include <__undef_macros>
38b3edf446SDimitry Andric 
39349cc55cSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
40349cc55cSDimitry Andric 
4106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
42349cc55cSDimitry Andric 
43349cc55cSDimitry Andric namespace ranges {
44349cc55cSDimitry Andric template <view _View>
45349cc55cSDimitry Andric   requires bidirectional_range<_View>
46349cc55cSDimitry Andric class reverse_view : public view_interface<reverse_view<_View>> {
47349cc55cSDimitry Andric   // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an
48349cc55cSDimitry Andric   // amortized O(1) begin() method.
49349cc55cSDimitry Andric   static constexpr bool _UseCache = !random_access_range<_View> && !common_range<_View>;
50349cc55cSDimitry Andric   using _Cache = _If<_UseCache, __non_propagating_cache<reverse_iterator<iterator_t<_View>>>, __empty_cache>;
5181ad6265SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache();
5281ad6265SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS _View __base_          = _View();
53349cc55cSDimitry Andric 
54349cc55cSDimitry Andric public:
55cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI reverse_view()
56cb14a3feSDimitry Andric     requires default_initializable<_View>
57cb14a3feSDimitry Andric   = default;
58349cc55cSDimitry Andric 
59cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit reverse_view(_View __view) : __base_(std::move(__view)) {}
60349cc55cSDimitry Andric 
61cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
62cb14a3feSDimitry Andric     requires copy_constructible<_View>
63cb14a3feSDimitry Andric   {
64cb14a3feSDimitry Andric     return __base_;
65cb14a3feSDimitry Andric   }
66349cc55cSDimitry Andric 
67cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
68349cc55cSDimitry Andric 
69cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin() {
70349cc55cSDimitry Andric     if constexpr (_UseCache)
71349cc55cSDimitry Andric       if (__cached_begin_.__has_value())
72349cc55cSDimitry Andric         return *__cached_begin_;
73349cc55cSDimitry Andric 
7481ad6265SDimitry Andric     auto __tmp = std::make_reverse_iterator(ranges::next(ranges::begin(__base_), ranges::end(__base_)));
75349cc55cSDimitry Andric     if constexpr (_UseCache)
76349cc55cSDimitry Andric       __cached_begin_.__emplace(__tmp);
77349cc55cSDimitry Andric     return __tmp;
78349cc55cSDimitry Andric   }
79349cc55cSDimitry Andric 
80cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin()
81cb14a3feSDimitry Andric     requires common_range<_View>
82cb14a3feSDimitry Andric   {
8381ad6265SDimitry Andric     return std::make_reverse_iterator(ranges::end(__base_));
84349cc55cSDimitry Andric   }
85349cc55cSDimitry Andric 
86cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
87cb14a3feSDimitry Andric     requires common_range<const _View>
88cb14a3feSDimitry Andric   {
8981ad6265SDimitry Andric     return std::make_reverse_iterator(ranges::end(__base_));
90349cc55cSDimitry Andric   }
91349cc55cSDimitry Andric 
92cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> end() {
9381ad6265SDimitry Andric     return std::make_reverse_iterator(ranges::begin(__base_));
94349cc55cSDimitry Andric   }
95349cc55cSDimitry Andric 
96cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
97cb14a3feSDimitry Andric     requires common_range<const _View>
98cb14a3feSDimitry Andric   {
9981ad6265SDimitry Andric     return std::make_reverse_iterator(ranges::begin(__base_));
100349cc55cSDimitry Andric   }
101349cc55cSDimitry Andric 
102cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto size()
103cb14a3feSDimitry Andric     requires sized_range<_View>
104cb14a3feSDimitry Andric   {
105349cc55cSDimitry Andric     return ranges::size(__base_);
106349cc55cSDimitry Andric   }
107349cc55cSDimitry Andric 
108cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
109cb14a3feSDimitry Andric     requires sized_range<const _View>
110cb14a3feSDimitry Andric   {
111349cc55cSDimitry Andric     return ranges::size(__base_);
112349cc55cSDimitry Andric   }
113349cc55cSDimitry Andric };
114349cc55cSDimitry Andric 
115349cc55cSDimitry Andric template <class _Range>
116349cc55cSDimitry Andric reverse_view(_Range&&) -> reverse_view<views::all_t<_Range>>;
117349cc55cSDimitry Andric 
118349cc55cSDimitry Andric template <class _Tp>
119349cc55cSDimitry Andric inline constexpr bool enable_borrowed_range<reverse_view<_Tp>> = enable_borrowed_range<_Tp>;
120349cc55cSDimitry Andric 
121349cc55cSDimitry Andric namespace views {
122349cc55cSDimitry Andric namespace __reverse {
123349cc55cSDimitry Andric template <class _Tp>
12481ad6265SDimitry Andric inline constexpr bool __is_reverse_view = false;
125349cc55cSDimitry Andric 
126349cc55cSDimitry Andric template <class _Tp>
12781ad6265SDimitry Andric inline constexpr bool __is_reverse_view<reverse_view<_Tp>> = true;
128349cc55cSDimitry Andric 
129349cc55cSDimitry Andric template <class _Tp>
13081ad6265SDimitry Andric inline constexpr bool __is_sized_reverse_subrange = false;
131349cc55cSDimitry Andric 
132349cc55cSDimitry Andric template <class _Iter>
133cb14a3feSDimitry Andric inline constexpr bool
134cb14a3feSDimitry Andric     __is_sized_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, subrange_kind::sized>> =
135cb14a3feSDimitry Andric         true;
136349cc55cSDimitry Andric 
137349cc55cSDimitry Andric template <class _Tp>
13881ad6265SDimitry Andric inline constexpr bool __is_unsized_reverse_subrange = false;
139349cc55cSDimitry Andric 
140349cc55cSDimitry Andric template <class _Iter, subrange_kind _Kind>
141cb14a3feSDimitry Andric inline constexpr bool __is_unsized_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> =
142cb14a3feSDimitry Andric     _Kind == subrange_kind::unsized;
143349cc55cSDimitry Andric 
144349cc55cSDimitry Andric template <class _Tp>
145349cc55cSDimitry Andric struct __unwrapped_reverse_subrange {
146cb14a3feSDimitry Andric   using type =
147cb14a3feSDimitry Andric       void; // avoid SFINAE-ing out the overload below -- let the concept requirements do it for better diagnostics
148349cc55cSDimitry Andric };
149349cc55cSDimitry Andric 
150349cc55cSDimitry Andric template <class _Iter, subrange_kind _Kind>
151349cc55cSDimitry Andric struct __unwrapped_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> {
152349cc55cSDimitry Andric   using type = subrange<_Iter, _Iter, _Kind>;
153349cc55cSDimitry Andric };
154349cc55cSDimitry Andric 
155349cc55cSDimitry Andric struct __fn : __range_adaptor_closure<__fn> {
156349cc55cSDimitry Andric   template <class _Range>
157349cc55cSDimitry Andric     requires __is_reverse_view<remove_cvref_t<_Range>>
158cb14a3feSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
159cb14a3feSDimitry Andric       noexcept(noexcept(std::forward<_Range>(__range).base())) -> decltype(std::forward<_Range>(__range).base()) {
160cb14a3feSDimitry Andric     return std::forward<_Range>(__range).base();
161cb14a3feSDimitry Andric   }
162349cc55cSDimitry Andric 
163349cc55cSDimitry Andric   template <class _Range,
164349cc55cSDimitry Andric             class _UnwrappedSubrange = typename __unwrapped_reverse_subrange<remove_cvref_t<_Range>>::type>
165349cc55cSDimitry Andric     requires __is_sized_reverse_subrange<remove_cvref_t<_Range>>
166cb14a3feSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
167349cc55cSDimitry Andric       noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size())))
168cb14a3feSDimitry Andric           -> decltype(_UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size())) {
169cb14a3feSDimitry Andric     return _UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size());
170cb14a3feSDimitry Andric   }
171349cc55cSDimitry Andric 
172349cc55cSDimitry Andric   template <class _Range,
173349cc55cSDimitry Andric             class _UnwrappedSubrange = typename __unwrapped_reverse_subrange<remove_cvref_t<_Range>>::type>
174349cc55cSDimitry Andric     requires __is_unsized_reverse_subrange<remove_cvref_t<_Range>>
175cb14a3feSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
176349cc55cSDimitry Andric       noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base())))
177cb14a3feSDimitry Andric           -> decltype(_UnwrappedSubrange(__range.end().base(), __range.begin().base())) {
178cb14a3feSDimitry Andric     return _UnwrappedSubrange(__range.end().base(), __range.begin().base());
179cb14a3feSDimitry Andric   }
180349cc55cSDimitry Andric 
181349cc55cSDimitry Andric   template <class _Range>
182cb14a3feSDimitry Andric     requires(!__is_reverse_view<remove_cvref_t<_Range>> && !__is_sized_reverse_subrange<remove_cvref_t<_Range>> &&
183349cc55cSDimitry Andric              !__is_unsized_reverse_subrange<remove_cvref_t<_Range>>)
184*0fca6ea1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const noexcept(noexcept(reverse_view{
185*0fca6ea1SDimitry Andric       std::forward<_Range>(__range)})) -> decltype(reverse_view{std::forward<_Range>(__range)}) {
186cb14a3feSDimitry Andric     return reverse_view{std::forward<_Range>(__range)};
187cb14a3feSDimitry Andric   }
188349cc55cSDimitry Andric };
1891fd87a68SDimitry Andric } // namespace __reverse
190349cc55cSDimitry Andric 
191349cc55cSDimitry Andric inline namespace __cpo {
192349cc55cSDimitry Andric inline constexpr auto reverse = __reverse::__fn{};
1931fd87a68SDimitry Andric } // namespace __cpo
194349cc55cSDimitry Andric } // namespace views
195349cc55cSDimitry Andric } // namespace ranges
196349cc55cSDimitry Andric 
19706c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
198349cc55cSDimitry Andric 
199349cc55cSDimitry Andric _LIBCPP_END_NAMESPACE_STD
200349cc55cSDimitry Andric 
201b3edf446SDimitry Andric _LIBCPP_POP_MACROS
202b3edf446SDimitry Andric 
203349cc55cSDimitry Andric #endif // _LIBCPP___RANGES_REVERSE_VIEW_H
204