1 // Copyright (C) 2019 T. Zachary Laine
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
9 #include <boost/stl_interfaces/iterator_interface.hpp>
12 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 {
15 template<typename Iter>
16 constexpr auto ce_dist(Iter f, Iter l, std::random_access_iterator_tag)
21 template<typename Iter, typename Tag>
22 constexpr auto ce_dist(Iter f, Iter l, Tag)
23 -> decltype(std::distance(f, l))
25 decltype(std::distance(f, l)) retval = 0;
32 template<typename Iter>
33 constexpr Iter ce_prev(Iter it)
38 template<typename Iter, typename Offset>
40 ce_adv(Iter & f, Offset n, std::random_access_iterator_tag)
44 template<typename Iter, typename Offset, typename Tag>
45 constexpr void ce_adv(Iter & f, Offset n, Tag)
48 for (Offset i = 0; i < n; ++i) {
52 for (Offset i = 0; i < -n; ++i) {
59 /** This type is very similar to the C++20 version of
60 `std::reverse_iterator`; it is `constexpr`-, `noexcept`-, and
62 template<typename BidiIter>
63 struct reverse_iterator
65 reverse_iterator<BidiIter>,
66 #if BOOST_STL_INTERFACES_USE_CONCEPTS
67 typename boost::stl_interfaces::v2::v2_dtl::iter_concept_t<
70 typename std::iterator_traits<BidiIter>::iterator_category,
72 typename std::iterator_traits<BidiIter>::value_type,
73 typename std::iterator_traits<BidiIter>::reference,
74 typename std::iterator_traits<BidiIter>::pointer,
75 typename std::iterator_traits<BidiIter>::difference_type>
77 constexpr reverse_iterator() noexcept(noexcept(BidiIter())) : it_() {}
78 constexpr reverse_iterator(BidiIter it) noexcept(
79 noexcept(BidiIter(it))) :
84 typename E = std::enable_if_t<
85 std::is_convertible<BidiIter2, BidiIter>::value>>
86 reverse_iterator(reverse_iterator<BidiIter2> const & it) : it_(it.it_)
89 friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR auto
90 operator-(reverse_iterator lhs, reverse_iterator rhs) noexcept(
91 noexcept(v1_dtl::ce_dist(
94 typename std::iterator_traits<BidiIter>::iterator_category{})))
96 return -v1_dtl::ce_dist(
99 typename std::iterator_traits<BidiIter>::iterator_category{});
102 constexpr typename std::iterator_traits<BidiIter>::reference
103 operator*() const noexcept(
104 noexcept(std::prev(v1_dtl::ce_prev(std::declval<BidiIter &>()))))
106 return *v1_dtl::ce_prev(it_);
109 constexpr reverse_iterator & operator+=(
110 typename std::iterator_traits<BidiIter>::difference_type
111 n) noexcept(noexcept(v1_dtl::
113 std::declval<BidiIter &>(),
115 typename std::iterator_traits<
117 iterator_category{})))
122 typename std::iterator_traits<BidiIter>::iterator_category{});
126 constexpr BidiIter base() const noexcept { return it_; }
130 constexpr BidiIter & base_reference() noexcept { return it_; }
131 constexpr BidiIter const & base_reference() const noexcept
136 template<typename BidiIter2>
137 friend struct reverse_iterator;
142 template<typename BidiIter>
143 constexpr auto operator==(
144 reverse_iterator<BidiIter> lhs,
145 reverse_iterator<BidiIter>
146 rhs) noexcept(noexcept(lhs.base() == rhs.base()))
147 -> decltype(rhs.base() == lhs.base())
149 return lhs.base() == rhs.base();
152 template<typename BidiIter1, typename BidiIter2>
153 constexpr auto operator==(
154 reverse_iterator<BidiIter1> lhs,
155 reverse_iterator<BidiIter2>
156 rhs) noexcept(noexcept(lhs.base() == rhs.base()))
157 -> decltype(rhs.base() == lhs.base())
159 return lhs.base() == rhs.base();
162 /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
164 template<typename BidiIter>
165 auto make_reverse_iterator(BidiIter it)
167 return reverse_iterator<BidiIter>(it);
173 #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
175 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
177 /** A template alias for `std::reverse_iterator`. This only exists to
178 make migration from Boost.STLInterfaces to C++20 easier; switch to the
179 one in `std` as soon as you can. */
180 template<typename BidiIter>
181 using reverse_iterator = std::reverse_iterator<BidiIter>;
184 /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
185 `Bidiiter`. This only exists to make migration from
186 Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
188 template<typename BidiIter>
189 auto make_reverse_iterator(BidiIter it)
191 return reverse_iterator<BidiIter>(it);