Horizon
reverse.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2014-present
5 //
6 // Use, modification and distribution is subject to the
7 // Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 
14 #ifndef RANGES_V3_VIEW_REVERSE_HPP
15 #define RANGES_V3_VIEW_REVERSE_HPP
16 
17 #include <iterator>
18 #include <utility>
19 
20 #include <meta/meta.hpp>
21 
22 #include <range/v3/range_fwd.hpp>
23 
29 #include <range/v3/utility/box.hpp>
30 #include <range/v3/utility/get.hpp>
32 #include <range/v3/utility/static_const.hpp>
34 #include <range/v3/view/all.hpp>
35 #include <range/v3/view/view.hpp>
36 
37 #include <range/v3/detail/prologue.hpp>
38 
39 namespace ranges
40 {
43  template<typename Rng>
44  struct RANGES_EMPTY_BASES reverse_view
45  : view_interface<reverse_view<Rng>, range_cardinality<Rng>::value>
46  , private detail::non_propagating_cache<iterator_t<Rng>, reverse_view<Rng>,
47  !common_range<Rng>>
48  {
49  private:
50  CPP_assert(bidirectional_range<Rng>);
51  Rng rng_;
52  constexpr reverse_iterator<iterator_t<Rng>> begin_(std::true_type)
53  {
54  return make_reverse_iterator(ranges::end(rng_));
55  }
56  constexpr reverse_iterator<iterator_t<Rng>> begin_(std::false_type)
57  {
58  using cache_t =
59  detail::non_propagating_cache<iterator_t<Rng>, reverse_view<Rng>>;
60  auto & end_ = static_cast<cache_t &>(*this);
61  if(!end_)
62  {
63 #if defined(_MSC_VER)
64  auto tmp = ranges::begin(rng_);
65  auto e = ranges::end(rng_);
66  while(tmp != e)
67  ++tmp;
68 #else
69  auto tmp = ranges::next(ranges::begin(rng_), ranges::end(rng_));
70 #endif
71  end_ = std::move(tmp);
72  }
73  return make_reverse_iterator(*end_);
74  }
75 
76  public:
77  reverse_view() = default;
78  constexpr explicit reverse_view(Rng rng)
79  : rng_(detail::move(rng))
80  {}
81  Rng base() const
82  {
83  return rng_;
84  }
85  constexpr reverse_iterator<iterator_t<Rng>> begin()
86  {
87  return begin_(meta::bool_<(bool)common_range<Rng>>{});
88  }
89  template(bool Const = true)(
90  requires Const AND common_range<meta::const_if_c<Const, Rng>>)
92  {
93  return make_reverse_iterator(ranges::end(rng_));
94  }
95  constexpr reverse_iterator<iterator_t<Rng>> end()
96  {
97  return make_reverse_iterator(ranges::begin(rng_));
98  }
99  template(bool Const = true)(
100  requires Const AND common_range<meta::const_if_c<Const, Rng>>)
102  {
103  return make_reverse_iterator(ranges::begin(rng_));
104  }
105  CPP_auto_member
106  constexpr auto CPP_fun(size)()(
107  requires sized_range<Rng>)
108  {
109  return ranges::size(rng_);
110  }
111  CPP_auto_member
112  constexpr auto CPP_fun(size)()(const //
113  requires sized_range<Rng const>)
114  {
115  return ranges::size(rng_);
116  }
117  };
118 
119  template<typename Rng>
120  struct reverse_view<reverse_view<Rng>> : Rng
121  {
122  CPP_assert(bidirectional_range<Rng>);
123  CPP_assert(
124  same_as<detail::decay_t<decltype(std::declval<reverse_view<Rng>>().base())>,
125  Rng>);
126 
127  reverse_view() = default;
128  constexpr explicit reverse_view(reverse_view<Rng> rng)
129  : Rng(rng.base())
130  {}
131 
132  constexpr reverse_view<Rng> base() const
133  {
134  return reverse_view<Rng>{*this};
135  }
136  };
137 
138  template<typename Rng>
139  RANGES_INLINE_VAR constexpr bool enable_borrowed_range<reverse_view<Rng>> =
140  enable_borrowed_range<Rng>;
141 
142 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
143  template<typename Rng>
144  reverse_view(Rng &&) //
146 
147  template<typename Rng>
150 #endif
151 
152  namespace views
153  {
154  struct reverse_fn
155  {
156  template(typename Rng)(
157  requires viewable_range<Rng> AND bidirectional_range<Rng>)
158  constexpr reverse_view<all_t<Rng>> operator()(Rng && rng) const
159  {
160  return reverse_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
161  }
162  };
163 
167  } // namespace views
168 
169  namespace cpp20
170  {
171  namespace views
172  {
173  using ranges::views::reverse;
174  }
175  template(typename Rng)(
176  requires view_<Rng> AND bidirectional_range<Rng>)
177  using reverse_view = ranges::reverse_view<Rng>;
178  } // namespace cpp20
180 } // namespace ranges
181 
182 #include <range/v3/detail/epilogue.hpp>
183 #include <range/v3/detail/satisfy_boost_range.hpp>
184 RANGES_SATISFY_BOOST_RANGE(::ranges::reverse_view)
185 
186 #endif
CPP_concept common_range
\concept common_range
Definition: concepts.hpp:180
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
Tiny meta-programming library.
Definition: basic_iterator.hpp:532
Definition: reverse.hpp:48
Definition: interface.hpp:129
Definition: reverse.hpp:155
Definition: view.hpp:178