File indexing completed on 2025-01-18 10:09:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_VIEW_REVERSE_HPP
0015 #define RANGES_V3_VIEW_REVERSE_HPP
0016
0017 #include <iterator>
0018 #include <utility>
0019
0020 #include <meta/meta.hpp>
0021
0022 #include <range/v3/range_fwd.hpp>
0023
0024 #include <range/v3/iterator/operations.hpp>
0025 #include <range/v3/iterator/reverse_iterator.hpp>
0026 #include <range/v3/range/access.hpp>
0027 #include <range/v3/range/primitives.hpp>
0028 #include <range/v3/range/traits.hpp>
0029 #include <range/v3/utility/box.hpp>
0030 #include <range/v3/utility/get.hpp>
0031 #include <range/v3/utility/optional.hpp>
0032 #include <range/v3/utility/static_const.hpp>
0033 #include <range/v3/view/adaptor.hpp>
0034 #include <range/v3/view/all.hpp>
0035 #include <range/v3/view/view.hpp>
0036
0037 #include <range/v3/detail/prologue.hpp>
0038
0039 namespace ranges
0040 {
0041
0042
0043 template<typename Rng>
0044 struct RANGES_EMPTY_BASES reverse_view
0045 : view_interface<reverse_view<Rng>, range_cardinality<Rng>::value>
0046 , private detail::non_propagating_cache<iterator_t<Rng>, reverse_view<Rng>,
0047 !common_range<Rng>>
0048 {
0049 private:
0050 CPP_assert(bidirectional_range<Rng>);
0051 Rng rng_;
0052 constexpr reverse_iterator<iterator_t<Rng>> begin_(std::true_type)
0053 {
0054 return make_reverse_iterator(ranges::end(rng_));
0055 }
0056 constexpr reverse_iterator<iterator_t<Rng>> begin_(std::false_type)
0057 {
0058 using cache_t =
0059 detail::non_propagating_cache<iterator_t<Rng>, reverse_view<Rng>>;
0060 auto & end_ = static_cast<cache_t &>(*this);
0061 if(!end_)
0062 {
0063 #if defined(_MSC_VER)
0064 auto tmp = ranges::begin(rng_);
0065 auto e = ranges::end(rng_);
0066 while(tmp != e)
0067 ++tmp;
0068 #else
0069 auto tmp = ranges::next(ranges::begin(rng_), ranges::end(rng_));
0070 #endif
0071 end_ = std::move(tmp);
0072 }
0073 return make_reverse_iterator(*end_);
0074 }
0075
0076 public:
0077 reverse_view() = default;
0078 constexpr explicit reverse_view(Rng rng)
0079 : rng_(detail::move(rng))
0080 {}
0081 Rng base() const
0082 {
0083 return rng_;
0084 }
0085 constexpr reverse_iterator<iterator_t<Rng>> begin()
0086 {
0087 return begin_(meta::bool_<(bool)common_range<Rng>>{});
0088 }
0089 template(bool Const = true)(
0090 requires Const AND common_range<meta::const_if_c<Const, Rng>>)
0091 constexpr reverse_iterator<iterator_t<meta::const_if_c<Const, Rng>>> begin() const
0092 {
0093 return make_reverse_iterator(ranges::end(rng_));
0094 }
0095 constexpr reverse_iterator<iterator_t<Rng>> end()
0096 {
0097 return make_reverse_iterator(ranges::begin(rng_));
0098 }
0099 template(bool Const = true)(
0100 requires Const AND common_range<meta::const_if_c<Const, Rng>>)
0101 constexpr reverse_iterator<iterator_t<meta::const_if_c<Const, Rng>>> end() const
0102 {
0103 return make_reverse_iterator(ranges::begin(rng_));
0104 }
0105 CPP_auto_member
0106 constexpr auto CPP_fun(size)()(
0107 requires sized_range<Rng>)
0108 {
0109 return ranges::size(rng_);
0110 }
0111 CPP_auto_member
0112 constexpr auto CPP_fun(size)()(const
0113 requires sized_range<Rng const>)
0114 {
0115 return ranges::size(rng_);
0116 }
0117 };
0118
0119 template<typename Rng>
0120 struct reverse_view<reverse_view<Rng>> : Rng
0121 {
0122 CPP_assert(bidirectional_range<Rng>);
0123 CPP_assert(
0124 same_as<detail::decay_t<decltype(std::declval<reverse_view<Rng>>().base())>,
0125 Rng>);
0126
0127 reverse_view() = default;
0128 constexpr explicit reverse_view(reverse_view<Rng> rng)
0129 : Rng(rng.base())
0130 {}
0131
0132 constexpr reverse_view<Rng> base() const
0133 {
0134 return reverse_view<Rng>{*this};
0135 }
0136 };
0137
0138 template<typename Rng>
0139 RANGES_INLINE_VAR constexpr bool enable_borrowed_range<reverse_view<Rng>> =
0140 enable_borrowed_range<Rng>;
0141
0142 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0143 template<typename Rng>
0144 reverse_view(Rng &&)
0145 -> reverse_view<views::all_t<Rng>>;
0146
0147 template<typename Rng>
0148 reverse_view(reverse_view<Rng>)
0149 -> reverse_view<reverse_view<Rng>>;
0150 #endif
0151
0152 namespace views
0153 {
0154 struct reverse_fn
0155 {
0156 template(typename Rng)(
0157 requires viewable_range<Rng> AND bidirectional_range<Rng>)
0158 constexpr reverse_view<all_t<Rng>> operator()(Rng && rng) const
0159 {
0160 return reverse_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
0161 }
0162 };
0163
0164
0165
0166 RANGES_INLINE_VARIABLE(view_closure<reverse_fn>, reverse)
0167 }
0168
0169 namespace cpp20
0170 {
0171 namespace views
0172 {
0173 using ranges::views::reverse;
0174 }
0175 template(typename Rng)(
0176 requires view_<Rng> AND bidirectional_range<Rng>)
0177 using reverse_view = ranges::reverse_view<Rng>;
0178 }
0179
0180 }
0181
0182 #include <range/v3/detail/epilogue.hpp>
0183 #include <range/v3/detail/satisfy_boost_range.hpp>
0184 RANGES_SATISFY_BOOST_RANGE(::ranges::reverse_view)
0185
0186 #endif