xref: /openbsd-src/gnu/llvm/libcxx/include/__ranges/reverse_view.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
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_REVERSE_VIEW_H
11*4bdff4beSrobert #define _LIBCPP___RANGES_REVERSE_VIEW_H
12*4bdff4beSrobert 
13*4bdff4beSrobert #include <__concepts/constructible.h>
14*4bdff4beSrobert #include <__config>
15*4bdff4beSrobert #include <__iterator/concepts.h>
16*4bdff4beSrobert #include <__iterator/next.h>
17*4bdff4beSrobert #include <__iterator/reverse_iterator.h>
18*4bdff4beSrobert #include <__ranges/access.h>
19*4bdff4beSrobert #include <__ranges/all.h>
20*4bdff4beSrobert #include <__ranges/concepts.h>
21*4bdff4beSrobert #include <__ranges/enable_borrowed_range.h>
22*4bdff4beSrobert #include <__ranges/non_propagating_cache.h>
23*4bdff4beSrobert #include <__ranges/range_adaptor.h>
24*4bdff4beSrobert #include <__ranges/size.h>
25*4bdff4beSrobert #include <__ranges/subrange.h>
26*4bdff4beSrobert #include <__ranges/view_interface.h>
27*4bdff4beSrobert #include <__utility/forward.h>
28*4bdff4beSrobert #include <__utility/move.h>
29*4bdff4beSrobert #include <type_traits>
30*4bdff4beSrobert 
31*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
32*4bdff4beSrobert #  pragma GCC system_header
33*4bdff4beSrobert #endif
34*4bdff4beSrobert 
35*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
36*4bdff4beSrobert 
37*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
38*4bdff4beSrobert 
39*4bdff4beSrobert namespace ranges {
40*4bdff4beSrobert   template<view _View>
41*4bdff4beSrobert     requires bidirectional_range<_View>
42*4bdff4beSrobert   class reverse_view : public view_interface<reverse_view<_View>> {
43*4bdff4beSrobert     // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an
44*4bdff4beSrobert     // amortized O(1) begin() method.
45*4bdff4beSrobert     static constexpr bool _UseCache = !random_access_range<_View> && !common_range<_View>;
46*4bdff4beSrobert     using _Cache = _If<_UseCache, __non_propagating_cache<reverse_iterator<iterator_t<_View>>>, __empty_cache>;
47*4bdff4beSrobert     _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache();
48*4bdff4beSrobert     _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
49*4bdff4beSrobert 
50*4bdff4beSrobert   public:
51*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
52*4bdff4beSrobert     reverse_view() requires default_initializable<_View> = default;
53*4bdff4beSrobert 
54*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
reverse_view(_View __view)55*4bdff4beSrobert     constexpr explicit reverse_view(_View __view) : __base_(std::move(__view)) {}
56*4bdff4beSrobert 
57*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
base()58*4bdff4beSrobert     constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
59*4bdff4beSrobert 
60*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
base()61*4bdff4beSrobert     constexpr _View base() && { return std::move(__base_); }
62*4bdff4beSrobert 
63*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
begin()64*4bdff4beSrobert     constexpr reverse_iterator<iterator_t<_View>> begin() {
65*4bdff4beSrobert       if constexpr (_UseCache)
66*4bdff4beSrobert         if (__cached_begin_.__has_value())
67*4bdff4beSrobert           return *__cached_begin_;
68*4bdff4beSrobert 
69*4bdff4beSrobert       auto __tmp = std::make_reverse_iterator(ranges::next(ranges::begin(__base_), ranges::end(__base_)));
70*4bdff4beSrobert       if constexpr (_UseCache)
71*4bdff4beSrobert         __cached_begin_.__emplace(__tmp);
72*4bdff4beSrobert       return __tmp;
73*4bdff4beSrobert     }
74*4bdff4beSrobert 
75*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
begin()76*4bdff4beSrobert     constexpr reverse_iterator<iterator_t<_View>> begin() requires common_range<_View> {
77*4bdff4beSrobert       return std::make_reverse_iterator(ranges::end(__base_));
78*4bdff4beSrobert     }
79*4bdff4beSrobert 
80*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
begin()81*4bdff4beSrobert     constexpr auto begin() const requires common_range<const _View> {
82*4bdff4beSrobert       return std::make_reverse_iterator(ranges::end(__base_));
83*4bdff4beSrobert     }
84*4bdff4beSrobert 
85*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
end()86*4bdff4beSrobert     constexpr reverse_iterator<iterator_t<_View>> end() {
87*4bdff4beSrobert       return std::make_reverse_iterator(ranges::begin(__base_));
88*4bdff4beSrobert     }
89*4bdff4beSrobert 
90*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
end()91*4bdff4beSrobert     constexpr auto end() const requires common_range<const _View> {
92*4bdff4beSrobert       return std::make_reverse_iterator(ranges::begin(__base_));
93*4bdff4beSrobert     }
94*4bdff4beSrobert 
95*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
size()96*4bdff4beSrobert     constexpr auto size() requires sized_range<_View> {
97*4bdff4beSrobert       return ranges::size(__base_);
98*4bdff4beSrobert     }
99*4bdff4beSrobert 
100*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
size()101*4bdff4beSrobert     constexpr auto size() const requires sized_range<const _View> {
102*4bdff4beSrobert       return ranges::size(__base_);
103*4bdff4beSrobert     }
104*4bdff4beSrobert   };
105*4bdff4beSrobert 
106*4bdff4beSrobert   template<class _Range>
107*4bdff4beSrobert   reverse_view(_Range&&) -> reverse_view<views::all_t<_Range>>;
108*4bdff4beSrobert 
109*4bdff4beSrobert   template<class _Tp>
110*4bdff4beSrobert   inline constexpr bool enable_borrowed_range<reverse_view<_Tp>> = enable_borrowed_range<_Tp>;
111*4bdff4beSrobert 
112*4bdff4beSrobert   namespace views {
113*4bdff4beSrobert   namespace __reverse {
114*4bdff4beSrobert     template<class _Tp>
115*4bdff4beSrobert     inline constexpr bool __is_reverse_view = false;
116*4bdff4beSrobert 
117*4bdff4beSrobert     template<class _Tp>
118*4bdff4beSrobert     inline constexpr bool __is_reverse_view<reverse_view<_Tp>> = true;
119*4bdff4beSrobert 
120*4bdff4beSrobert     template<class _Tp>
121*4bdff4beSrobert     inline constexpr bool __is_sized_reverse_subrange = false;
122*4bdff4beSrobert 
123*4bdff4beSrobert     template<class _Iter>
124*4bdff4beSrobert     inline constexpr bool __is_sized_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, subrange_kind::sized>> = true;
125*4bdff4beSrobert 
126*4bdff4beSrobert     template<class _Tp>
127*4bdff4beSrobert     inline constexpr bool __is_unsized_reverse_subrange = false;
128*4bdff4beSrobert 
129*4bdff4beSrobert     template<class _Iter, subrange_kind _Kind>
130*4bdff4beSrobert     inline constexpr bool __is_unsized_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> = _Kind == subrange_kind::unsized;
131*4bdff4beSrobert 
132*4bdff4beSrobert     template<class _Tp>
133*4bdff4beSrobert     struct __unwrapped_reverse_subrange {
134*4bdff4beSrobert       using type = void; // avoid SFINAE-ing out the overload below -- let the concept requirements do it for better diagnostics
135*4bdff4beSrobert     };
136*4bdff4beSrobert 
137*4bdff4beSrobert     template<class _Iter, subrange_kind _Kind>
138*4bdff4beSrobert     struct __unwrapped_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> {
139*4bdff4beSrobert       using type = subrange<_Iter, _Iter, _Kind>;
140*4bdff4beSrobert     };
141*4bdff4beSrobert 
142*4bdff4beSrobert     struct __fn : __range_adaptor_closure<__fn> {
143*4bdff4beSrobert       template<class _Range>
144*4bdff4beSrobert         requires __is_reverse_view<remove_cvref_t<_Range>>
145*4bdff4beSrobert       [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
146*4bdff4beSrobert       constexpr auto operator()(_Range&& __range) const
147*4bdff4beSrobert         noexcept(noexcept(std::forward<_Range>(__range).base()))
148*4bdff4beSrobert         -> decltype(      std::forward<_Range>(__range).base())
149*4bdff4beSrobert         { return          std::forward<_Range>(__range).base(); }
150*4bdff4beSrobert 
151*4bdff4beSrobert       template<class _Range,
152*4bdff4beSrobert                class _UnwrappedSubrange = typename __unwrapped_reverse_subrange<remove_cvref_t<_Range>>::type>
153*4bdff4beSrobert         requires __is_sized_reverse_subrange<remove_cvref_t<_Range>>
154*4bdff4beSrobert       [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
155*4bdff4beSrobert       constexpr auto operator()(_Range&& __range) const
156*4bdff4beSrobert         noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size())))
157*4bdff4beSrobert         -> decltype(      _UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size()))
158*4bdff4beSrobert         { return          _UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size()); }
159*4bdff4beSrobert 
160*4bdff4beSrobert       template<class _Range,
161*4bdff4beSrobert                class _UnwrappedSubrange = typename __unwrapped_reverse_subrange<remove_cvref_t<_Range>>::type>
162*4bdff4beSrobert         requires __is_unsized_reverse_subrange<remove_cvref_t<_Range>>
163*4bdff4beSrobert       [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
164*4bdff4beSrobert       constexpr auto operator()(_Range&& __range) const
165*4bdff4beSrobert         noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base())))
166*4bdff4beSrobert         -> decltype(      _UnwrappedSubrange(__range.end().base(), __range.begin().base()))
167*4bdff4beSrobert         { return          _UnwrappedSubrange(__range.end().base(), __range.begin().base()); }
168*4bdff4beSrobert 
169*4bdff4beSrobert       template<class _Range>
170*4bdff4beSrobert         requires (!__is_reverse_view<remove_cvref_t<_Range>> &&
171*4bdff4beSrobert                   !__is_sized_reverse_subrange<remove_cvref_t<_Range>> &&
172*4bdff4beSrobert                   !__is_unsized_reverse_subrange<remove_cvref_t<_Range>>)
173*4bdff4beSrobert       [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
174*4bdff4beSrobert       constexpr auto operator()(_Range&& __range) const
175*4bdff4beSrobert         noexcept(noexcept(reverse_view{std::forward<_Range>(__range)}))
176*4bdff4beSrobert         -> decltype(      reverse_view{std::forward<_Range>(__range)})
177*4bdff4beSrobert         { return          reverse_view{std::forward<_Range>(__range)}; }
178*4bdff4beSrobert     };
179*4bdff4beSrobert   } // namespace __reverse
180*4bdff4beSrobert 
181*4bdff4beSrobert   inline namespace __cpo {
182*4bdff4beSrobert     inline constexpr auto reverse = __reverse::__fn{};
183*4bdff4beSrobert   } // namespace __cpo
184*4bdff4beSrobert   } // namespace views
185*4bdff4beSrobert } // namespace ranges
186*4bdff4beSrobert 
187*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
188*4bdff4beSrobert 
189*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
190*4bdff4beSrobert 
191*4bdff4beSrobert #endif // _LIBCPP___RANGES_REVERSE_VIEW_H
192