reverse_iterator.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 { inline 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. reverse_iterator<BidiIter>,
  59. #if 201703L < __cplusplus && defined(__cpp_lib_ranges)
  60. typename v2::detail::iter_concept_t<BidiIter>,
  61. #else
  62. typename std::iterator_traits<BidiIter>::iterator_category,
  63. #endif
  64. typename std::iterator_traits<BidiIter>::value_type,
  65. typename std::iterator_traits<BidiIter>::reference,
  66. typename std::iterator_traits<BidiIter>::pointer,
  67. typename std::iterator_traits<BidiIter>::difference_type>
  68. {
  69. constexpr reverse_iterator() noexcept(noexcept(BidiIter())) : it_() {}
  70. constexpr reverse_iterator(BidiIter it) noexcept(
  71. noexcept(BidiIter(it))) :
  72. it_(it)
  73. {}
  74. template<
  75. typename BidiIter2,
  76. typename E = std::enable_if_t<
  77. std::is_convertible<BidiIter2, BidiIter>::value>>
  78. reverse_iterator(reverse_iterator<BidiIter2> const & it) : it_(it.it_)
  79. {}
  80. friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR auto
  81. operator-(reverse_iterator lhs, reverse_iterator rhs) noexcept(
  82. noexcept(v1_dtl::ce_dist(
  83. lhs.it_,
  84. rhs.it_,
  85. typename std::iterator_traits<BidiIter>::iterator_category{})))
  86. {
  87. return -v1_dtl::ce_dist(
  88. rhs.it_,
  89. lhs.it_,
  90. typename std::iterator_traits<BidiIter>::iterator_category{});
  91. }
  92. constexpr typename std::iterator_traits<BidiIter>::reference
  93. operator*() const noexcept(
  94. noexcept(std::prev(v1_dtl::ce_prev(std::declval<BidiIter &>()))))
  95. {
  96. return *v1_dtl::ce_prev(it_);
  97. }
  98. constexpr reverse_iterator & operator+=(
  99. typename std::iterator_traits<BidiIter>::difference_type
  100. n) noexcept(noexcept(v1_dtl::
  101. ce_adv(
  102. std::declval<BidiIter &>(),
  103. -n,
  104. typename std::iterator_traits<
  105. BidiIter>::
  106. iterator_category{})))
  107. {
  108. v1_dtl::ce_adv(
  109. it_,
  110. -n,
  111. typename std::iterator_traits<BidiIter>::iterator_category{});
  112. return *this;
  113. }
  114. constexpr BidiIter base() const noexcept { return it_; }
  115. private:
  116. friend access;
  117. constexpr BidiIter & base_reference() noexcept { return it_; }
  118. constexpr BidiIter const & base_reference() const noexcept
  119. {
  120. return it_;
  121. }
  122. template<typename BidiIter2>
  123. friend struct reverse_iterator;
  124. BidiIter it_;
  125. };
  126. template<typename BidiIter>
  127. constexpr auto operator==(
  128. reverse_iterator<BidiIter> lhs,
  129. reverse_iterator<BidiIter>
  130. rhs) noexcept(noexcept(lhs.base() == rhs.base()))
  131. -> decltype(rhs.base() == lhs.base())
  132. {
  133. return lhs.base() == rhs.base();
  134. }
  135. template<typename BidiIter1, typename BidiIter2>
  136. constexpr auto operator==(
  137. reverse_iterator<BidiIter1> lhs,
  138. reverse_iterator<BidiIter2>
  139. rhs) noexcept(noexcept(lhs.base() == rhs.base()))
  140. -> decltype(rhs.base() == lhs.base())
  141. {
  142. return lhs.base() == rhs.base();
  143. }
  144. /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
  145. `Bidiiter`. */
  146. template<typename BidiIter>
  147. auto make_reverse_iterator(BidiIter it)
  148. {
  149. return reverse_iterator<BidiIter>(it);
  150. }
  151. }}}
  152. #if 201703L < __cplusplus && defined(__cpp_lib_concepts) || \
  153. defined(BOOST_STL_INTERFACES_DOXYGEN)
  154. namespace boost { namespace stl_interfaces { namespace v2 {
  155. /** A template alias for `std::reverse_iterator`. This only exists to
  156. make migration from Boost.STLInterfaces to C++20 easier; switch to the
  157. one in `std` as soon as you can. */
  158. template<typename BidiIter>
  159. using reverse_iterator = std::reverse_iterator<BidiIter>;
  160. /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
  161. `Bidiiter`. This only exists to make migration from
  162. Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
  163. soon as you can. */
  164. template<typename BidiIter>
  165. auto make_reverse_iterator(BidiIter it)
  166. {
  167. return reverse_iterator<BidiIter>(it);
  168. }
  169. }}}
  170. #endif
  171. #endif