reverse.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /// \file
  2. // 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. #ifndef RANGES_V3_VIEW_REVERSE_HPP
  14. #define RANGES_V3_VIEW_REVERSE_HPP
  15. #include <iterator>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/iterator/operations.hpp>
  20. #include <range/v3/iterator/reverse_iterator.hpp>
  21. #include <range/v3/range/access.hpp>
  22. #include <range/v3/range/primitives.hpp>
  23. #include <range/v3/range/traits.hpp>
  24. #include <range/v3/utility/box.hpp>
  25. #include <range/v3/utility/get.hpp>
  26. #include <range/v3/utility/optional.hpp>
  27. #include <range/v3/utility/static_const.hpp>
  28. #include <range/v3/view/adaptor.hpp>
  29. #include <range/v3/view/all.hpp>
  30. #include <range/v3/view/view.hpp>
  31. #include <range/v3/detail/prologue.hpp>
  32. namespace ranges
  33. {
  34. /// \addtogroup group-views
  35. /// @{
  36. template<typename Rng>
  37. struct RANGES_EMPTY_BASES reverse_view
  38. : view_interface<reverse_view<Rng>, range_cardinality<Rng>::value>
  39. , private detail::non_propagating_cache<iterator_t<Rng>, reverse_view<Rng>,
  40. !common_range<Rng>>
  41. {
  42. private:
  43. CPP_assert(bidirectional_range<Rng>);
  44. Rng rng_;
  45. constexpr reverse_iterator<iterator_t<Rng>> begin_(std::true_type)
  46. {
  47. return make_reverse_iterator(ranges::end(rng_));
  48. }
  49. constexpr reverse_iterator<iterator_t<Rng>> begin_(std::false_type)
  50. {
  51. using cache_t =
  52. detail::non_propagating_cache<iterator_t<Rng>, reverse_view<Rng>>;
  53. auto & end_ = static_cast<cache_t &>(*this);
  54. if(!end_)
  55. {
  56. #if defined(_MSC_VER)
  57. auto tmp = ranges::begin(rng_);
  58. auto e = ranges::end(rng_);
  59. while(tmp != e)
  60. ++tmp;
  61. #else
  62. auto tmp = ranges::next(ranges::begin(rng_), ranges::end(rng_));
  63. #endif
  64. end_ = std::move(tmp);
  65. }
  66. return make_reverse_iterator(*end_);
  67. }
  68. public:
  69. reverse_view() = default;
  70. constexpr explicit reverse_view(Rng rng)
  71. : rng_(detail::move(rng))
  72. {}
  73. Rng base() const
  74. {
  75. return rng_;
  76. }
  77. constexpr reverse_iterator<iterator_t<Rng>> begin()
  78. {
  79. return begin_(meta::bool_<(bool)common_range<Rng>>{});
  80. }
  81. template(bool Const = true)(
  82. requires Const AND common_range<meta::const_if_c<Const, Rng>>)
  83. constexpr reverse_iterator<iterator_t<meta::const_if_c<Const, Rng>>> begin() const
  84. {
  85. return make_reverse_iterator(ranges::end(rng_));
  86. }
  87. constexpr reverse_iterator<iterator_t<Rng>> end()
  88. {
  89. return make_reverse_iterator(ranges::begin(rng_));
  90. }
  91. template(bool Const = true)(
  92. requires Const AND common_range<meta::const_if_c<Const, Rng>>)
  93. constexpr reverse_iterator<iterator_t<meta::const_if_c<Const, Rng>>> end() const
  94. {
  95. return make_reverse_iterator(ranges::begin(rng_));
  96. }
  97. CPP_auto_member
  98. constexpr auto CPP_fun(size)()(
  99. requires sized_range<Rng>)
  100. {
  101. return ranges::size(rng_);
  102. }
  103. CPP_auto_member
  104. constexpr auto CPP_fun(size)()(const //
  105. requires sized_range<Rng const>)
  106. {
  107. return ranges::size(rng_);
  108. }
  109. };
  110. template<typename Rng>
  111. struct reverse_view<reverse_view<Rng>> : Rng
  112. {
  113. CPP_assert(bidirectional_range<Rng>);
  114. CPP_assert(
  115. same_as<detail::decay_t<decltype(std::declval<reverse_view<Rng>>().base())>,
  116. Rng>);
  117. reverse_view() = default;
  118. constexpr explicit reverse_view(reverse_view<Rng> rng)
  119. : Rng(rng.base())
  120. {}
  121. constexpr reverse_view<Rng> base() const
  122. {
  123. return reverse_view<Rng>{*this};
  124. }
  125. };
  126. template<typename Rng>
  127. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<reverse_view<Rng>> =
  128. enable_borrowed_range<Rng>;
  129. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  130. template<typename Rng>
  131. reverse_view(Rng &&) //
  132. -> reverse_view<views::all_t<Rng>>;
  133. template<typename Rng>
  134. reverse_view(reverse_view<Rng>)
  135. -> reverse_view<reverse_view<Rng>>;
  136. #endif
  137. namespace views
  138. {
  139. struct reverse_fn
  140. {
  141. template(typename Rng)(
  142. requires viewable_range<Rng> AND bidirectional_range<Rng>)
  143. constexpr reverse_view<all_t<Rng>> operator()(Rng && rng) const
  144. {
  145. return reverse_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
  146. }
  147. };
  148. /// \relates reverse_fn
  149. /// \ingroup group-views
  150. RANGES_INLINE_VARIABLE(view_closure<reverse_fn>, reverse)
  151. } // namespace views
  152. namespace cpp20
  153. {
  154. namespace views
  155. {
  156. using ranges::views::reverse;
  157. }
  158. template(typename Rng)(
  159. requires view_<Rng> AND bidirectional_range<Rng>)
  160. using reverse_view = ranges::reverse_view<Rng>;
  161. } // namespace cpp20
  162. /// @}
  163. } // namespace ranges
  164. #include <range/v3/detail/epilogue.hpp>
  165. #include <range/v3/detail/satisfy_boost_range.hpp>
  166. RANGES_SATISFY_BOOST_RANGE(::ranges::reverse_view)
  167. #endif