• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 #include <boost/stl_interfaces/iterator_interface.hpp>
10 
11 
12 namespace boost { namespace stl_interfaces { inline namespace v1 {
13 
14     namespace v1_dtl {
15         template<typename Iter>
ce_dist(Iter f,Iter l,std::random_access_iterator_tag)16         constexpr auto ce_dist(Iter f, Iter l, std::random_access_iterator_tag)
17             -> decltype(l - f)
18         {
19             return l - f;
20         }
21         template<typename Iter, typename Tag>
ce_dist(Iter f,Iter l,Tag)22         constexpr auto ce_dist(Iter f, Iter l, Tag)
23             -> decltype(std::distance(f, l))
24         {
25             decltype(std::distance(f, l)) retval = 0;
26             for (; f != l; ++f) {
27                 ++retval;
28             }
29             return retval;
30         }
31 
32         template<typename Iter>
ce_prev(Iter it)33         constexpr Iter ce_prev(Iter it)
34         {
35             return --it;
36         }
37 
38         template<typename Iter, typename Offset>
39         constexpr void
ce_adv(Iter & f,Offset n,std::random_access_iterator_tag)40         ce_adv(Iter & f, Offset n, std::random_access_iterator_tag)
41         {
42             f += n;
43         }
44         template<typename Iter, typename Offset, typename Tag>
ce_adv(Iter & f,Offset n,Tag)45         constexpr void ce_adv(Iter & f, Offset n, Tag)
46         {
47             if (0 < n) {
48                 for (Offset i = 0; i < n; ++i) {
49                     ++f;
50                 }
51             } else {
52                 for (Offset i = 0; i < -n; ++i) {
53                     --f;
54                 }
55             }
56         }
57     }
58 
59     /** This type is very similar to the C++20 version of
60         `std::reverse_iterator`; it is `constexpr`-, `noexcept`-, and
61         proxy-friendly. */
62     template<typename BidiIter>
63     struct reverse_iterator
64         : iterator_interface<
65               reverse_iterator<BidiIter>,
66 #if 201703L < __cplusplus && defined(__cpp_lib_ranges)
67               typename v2::detail::iter_concept_t<BidiIter>,
68 #else
69               typename std::iterator_traits<BidiIter>::iterator_category,
70 #endif
71               typename std::iterator_traits<BidiIter>::value_type,
72               typename std::iterator_traits<BidiIter>::reference,
73               typename std::iterator_traits<BidiIter>::pointer,
74               typename std::iterator_traits<BidiIter>::difference_type>
75     {
reverse_iteratorboost::stl_interfaces::v1::reverse_iterator76         constexpr reverse_iterator() noexcept(noexcept(BidiIter())) : it_() {}
reverse_iteratorboost::stl_interfaces::v1::reverse_iterator77         constexpr reverse_iterator(BidiIter it) noexcept(
78             noexcept(BidiIter(it))) :
79             it_(it)
80         {}
81         template<
82             typename BidiIter2,
83             typename E = std::enable_if_t<
84                 std::is_convertible<BidiIter2, BidiIter>::value>>
reverse_iteratorboost::stl_interfaces::v1::reverse_iterator85         reverse_iterator(reverse_iterator<BidiIter2> const & it) : it_(it.it_)
86         {}
87 
88         friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR auto
operator -(reverse_iterator lhs,reverse_iterator rhs)89         operator-(reverse_iterator lhs, reverse_iterator rhs) noexcept(
90             noexcept(v1_dtl::ce_dist(
91                 lhs.it_,
92                 rhs.it_,
93                 typename std::iterator_traits<BidiIter>::iterator_category{})))
94         {
95             return -v1_dtl::ce_dist(
96                 rhs.it_,
97                 lhs.it_,
98                 typename std::iterator_traits<BidiIter>::iterator_category{});
99         }
100 
101         constexpr typename std::iterator_traits<BidiIter>::reference
operator *boost::stl_interfaces::v1::reverse_iterator102         operator*() const noexcept(
103             noexcept(std::prev(v1_dtl::ce_prev(std::declval<BidiIter &>()))))
104         {
105             return *v1_dtl::ce_prev(it_);
106         }
107 
operator +=boost::stl_interfaces::v1::reverse_iterator108         constexpr reverse_iterator & operator+=(
109             typename std::iterator_traits<BidiIter>::difference_type
110                 n) noexcept(noexcept(v1_dtl::
111                                          ce_adv(
112                                              std::declval<BidiIter &>(),
113                                              -n,
114                                              typename std::iterator_traits<
115                                                  BidiIter>::
116                                                  iterator_category{})))
117         {
118             v1_dtl::ce_adv(
119                 it_,
120                 -n,
121                 typename std::iterator_traits<BidiIter>::iterator_category{});
122             return *this;
123         }
124 
baseboost::stl_interfaces::v1::reverse_iterator125         constexpr BidiIter base() const noexcept { return it_; }
126 
127     private:
128         friend access;
base_referenceboost::stl_interfaces::v1::reverse_iterator129         constexpr BidiIter & base_reference() noexcept { return it_; }
base_referenceboost::stl_interfaces::v1::reverse_iterator130         constexpr BidiIter const & base_reference() const noexcept
131         {
132             return it_;
133         }
134 
135         template<typename BidiIter2>
136         friend struct reverse_iterator;
137 
138         BidiIter it_;
139     };
140 
141     template<typename BidiIter>
operator ==(reverse_iterator<BidiIter> lhs,reverse_iterator<BidiIter> rhs)142     constexpr auto operator==(
143         reverse_iterator<BidiIter> lhs,
144         reverse_iterator<BidiIter>
145             rhs) noexcept(noexcept(lhs.base() == rhs.base()))
146         -> decltype(rhs.base() == lhs.base())
147     {
148         return lhs.base() == rhs.base();
149     }
150 
151     template<typename BidiIter1, typename BidiIter2>
operator ==(reverse_iterator<BidiIter1> lhs,reverse_iterator<BidiIter2> rhs)152     constexpr auto operator==(
153         reverse_iterator<BidiIter1> lhs,
154         reverse_iterator<BidiIter2>
155             rhs) noexcept(noexcept(lhs.base() == rhs.base()))
156         -> decltype(rhs.base() == lhs.base())
157     {
158         return lhs.base() == rhs.base();
159     }
160 
161     /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
162         `Bidiiter`. */
163     template<typename BidiIter>
make_reverse_iterator(BidiIter it)164     auto make_reverse_iterator(BidiIter it)
165     {
166         return reverse_iterator<BidiIter>(it);
167     }
168 
169 }}}
170 
171 
172 #if 201703L < __cplusplus && defined(__cpp_lib_concepts) ||                    \
173     defined(BOOST_STL_INTERFACES_DOXYGEN)
174 
175 namespace boost { namespace stl_interfaces { namespace v2 {
176 
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>;
182 
183 
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
187         soon as you can. */
188     template<typename BidiIter>
make_reverse_iterator(BidiIter it)189     auto make_reverse_iterator(BidiIter it)
190     {
191         return reverse_iterator<BidiIter>(it);
192     }
193 
194 }}}
195 
196 #endif
197 
198 #endif
199