reverse_iterator.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright (C) 2019 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_STL_INTERFACES_REVERSE_ITERATOR_HPP
  7. #define BOOST_STL_INTERFACES_REVERSE_ITERATOR_HPP
  8. #include <boost/stl_interfaces/iterator_interface.hpp>
  9. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 {
  10. namespace v1_dtl {
  11. template<typename Iter>
  12. constexpr auto ce_dist(Iter f, Iter l, std::random_access_iterator_tag)
  13. -> decltype(l - f)
  14. {
  15. return l - f;
  16. }
  17. template<typename Iter, typename Tag>
  18. constexpr auto ce_dist(Iter f, Iter l, Tag)
  19. -> decltype(std::distance(f, l))
  20. {
  21. decltype(std::distance(f, l)) retval = 0;
  22. for (; f != l; ++f) {
  23. ++retval;
  24. }
  25. return retval;
  26. }
  27. template<typename Iter>
  28. constexpr Iter ce_prev(Iter it)
  29. {
  30. return --it;
  31. }
  32. template<typename Iter, typename Offset>
  33. constexpr void
  34. ce_adv(Iter & f, Offset n, std::random_access_iterator_tag)
  35. {
  36. f += n;
  37. }
  38. template<typename Iter, typename Offset, typename Tag>
  39. constexpr void ce_adv(Iter & f, Offset n, Tag)
  40. {
  41. if (0 < n) {
  42. for (Offset i = 0; i < n; ++i) {
  43. ++f;
  44. }
  45. } else {
  46. for (Offset i = 0; i < -n; ++i) {
  47. --f;
  48. }
  49. }
  50. }
  51. }
  52. /** This type is very similar to the C++20 version of
  53. `std::reverse_iterator`; it is `constexpr`-, `noexcept`-, and
  54. proxy-friendly. */
  55. template<typename BidiIter>
  56. struct reverse_iterator
  57. : iterator_interface<
  58. #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
  59. reverse_iterator<BidiIter>,
  60. #endif
  61. #if BOOST_STL_INTERFACES_USE_CONCEPTS
  62. typename boost::stl_interfaces::v2::v2_dtl::iter_concept_t<
  63. BidiIter>,
  64. #else
  65. typename std::iterator_traits<BidiIter>::iterator_category,
  66. #endif
  67. typename std::iterator_traits<BidiIter>::value_type,
  68. typename std::iterator_traits<BidiIter>::reference,
  69. typename std::iterator_traits<BidiIter>::pointer,
  70. typename std::iterator_traits<BidiIter>::difference_type>
  71. {
  72. constexpr reverse_iterator() noexcept(noexcept(BidiIter())) : it_() {}
  73. constexpr reverse_iterator(BidiIter it) noexcept(
  74. noexcept(BidiIter(it))) :
  75. it_(it)
  76. {}
  77. template<
  78. typename BidiIter2,
  79. typename E = std::enable_if_t<
  80. std::is_convertible<BidiIter2, BidiIter>::value>>
  81. reverse_iterator(reverse_iterator<BidiIter2> const & it) : it_(it.it_)
  82. {}
  83. friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR auto
  84. operator-(reverse_iterator lhs, reverse_iterator rhs) noexcept(
  85. noexcept(v1_dtl::ce_dist(
  86. lhs.it_,
  87. rhs.it_,
  88. typename std::iterator_traits<BidiIter>::iterator_category{})))
  89. {
  90. return -v1_dtl::ce_dist(
  91. rhs.it_,
  92. lhs.it_,
  93. typename std::iterator_traits<BidiIter>::iterator_category{});
  94. }
  95. constexpr typename std::iterator_traits<BidiIter>::reference
  96. operator*() const noexcept(
  97. noexcept(std::prev(v1_dtl::ce_prev(std::declval<BidiIter &>()))))
  98. {
  99. return *v1_dtl::ce_prev(it_);
  100. }
  101. constexpr reverse_iterator & operator+=(
  102. typename std::iterator_traits<BidiIter>::difference_type
  103. n) noexcept(noexcept(v1_dtl::
  104. ce_adv(
  105. std::declval<BidiIter &>(),
  106. -n,
  107. typename std::iterator_traits<
  108. BidiIter>::
  109. iterator_category{})))
  110. {
  111. v1_dtl::ce_adv(
  112. it_,
  113. -n,
  114. typename std::iterator_traits<BidiIter>::iterator_category{});
  115. return *this;
  116. }
  117. constexpr BidiIter base() const noexcept { return it_; }
  118. private:
  119. friend access;
  120. constexpr BidiIter & base_reference() noexcept { return it_; }
  121. constexpr BidiIter const & base_reference() const noexcept
  122. {
  123. return it_;
  124. }
  125. template<typename BidiIter2>
  126. friend struct reverse_iterator;
  127. BidiIter it_;
  128. };
  129. template<typename BidiIter>
  130. constexpr auto operator==(
  131. reverse_iterator<BidiIter> lhs,
  132. reverse_iterator<BidiIter>
  133. rhs) noexcept(noexcept(lhs.base() == rhs.base()))
  134. -> decltype(rhs.base() == lhs.base())
  135. {
  136. return lhs.base() == rhs.base();
  137. }
  138. template<typename BidiIter1, typename BidiIter2>
  139. constexpr auto operator==(
  140. reverse_iterator<BidiIter1> lhs,
  141. reverse_iterator<BidiIter2>
  142. rhs) noexcept(noexcept(lhs.base() == rhs.base()))
  143. -> decltype(rhs.base() == lhs.base())
  144. {
  145. return lhs.base() == rhs.base();
  146. }
  147. /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
  148. `BidiIter`. */
  149. template<typename BidiIter>
  150. auto make_reverse_iterator(BidiIter it)
  151. {
  152. return reverse_iterator<BidiIter>(it);
  153. }
  154. }}}
  155. #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
  156. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
  157. /** A template alias for `std::reverse_iterator`. This only exists to
  158. make migration from Boost.STLInterfaces to C++20 easier; switch to the
  159. one in `std` as soon as you can. */
  160. template<typename BidiIter>
  161. using reverse_iterator = std::reverse_iterator<BidiIter>;
  162. /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
  163. `BidiIter`. This only exists to make migration from
  164. Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
  165. soon as you can. */
  166. template<typename BidiIter>
  167. auto make_reverse_iterator(BidiIter it)
  168. {
  169. return reverse_iterator<BidiIter>(it);
  170. }
  171. }}}
  172. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 {
  173. /** A template alias for `std::reverse_iterator`. This only exists to
  174. make migration from Boost.STLInterfaces to C++20 easier; switch to the
  175. one in `std` as soon as you can. */
  176. template<typename BidiIter>
  177. using reverse_iterator = std::reverse_iterator<BidiIter>;
  178. /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
  179. `BidiIter`. This only exists to make migration from
  180. Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
  181. soon as you can. */
  182. template<typename BidiIter>
  183. auto make_reverse_iterator(BidiIter it)
  184. {
  185. return reverse_iterator<BidiIter>(it);
  186. }
  187. }}}
  188. #endif
  189. #endif