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//[ reverse_iterator
7#include <boost/stl_interfaces/iterator_interface.hpp>
8
9#include <algorithm>
10#include <list>
11#include <vector>
12
13#include <cassert>
14
15
16// In all the previous examples, we only had to implement a subset of the six
17// possible user-defined basis operations that was needed for one particular
18// iterator concept. For reverse_iterator, we want to support bidirectional,
19// random access, and contiguous iterators. We therefore need to provide all
20// the basis operations that might be needed.
21template<typename BidiIter>
22struct reverse_iterator
23 : boost::stl_interfaces::iterator_interface<
24#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
25 reverse_iterator<BidiIter>,
26#endif
27#if 201703L < __cplusplus && defined(__cpp_lib_ranges)
28 boost::stl_interfaces::v2::v2_dtl::iter_concept_t<BidiIter>,
29#else
30 typename std::iterator_traits<BidiIter>::iterator_category,
31#endif
32 typename std::iterator_traits<BidiIter>::value_type>
33{
34 reverse_iterator() : it_() {}
35 reverse_iterator(BidiIter it) : it_(it) {}
36
37 using ref_t = typename std::iterator_traits<BidiIter>::reference;
38 using diff_t = typename std::iterator_traits<BidiIter>::difference_type;
39
40 ref_t operator*() const { return *std::prev(it_); }
41
42 // These three are used only when BidiIter::iterator_category is
43 // std::bidirectional_iterator_tag.
44 bool operator==(reverse_iterator other) const { return it_ == other.it_; }
45
46 // Even though iterator_interface-derived bidirectional iterators are
47 // usually given operator++() and operator--() members, it turns out that
48 // operator+=() below amounts to the same thing. That's good, since
49 // having operator++() and operator+=() in this class would have lead to
50 // ambiguities in iterator_interface.
51
52 // These two are only used when BidiIter::iterator_category is
53 // std::random_access_iterator_tag or std::contiguous_iterator_tag. Even
54 // so, they need to compile even when BidiIter::iterator_category is
55 // std::bidirectional_iterator_tag. That means we have to use
56 // std::distance() and std::advance() instead of operator-() and
57 // operator+=().
58 //
59 // Don't worry, the O(n) bidirectional implementations of std::distance()
60 // and std::advance() are dead code, because compare() and advance() are
61 // never even called when BidiIter::iterator_category is
62 // std::bidirectional_iterator_tag.
63 diff_t operator-(reverse_iterator other) const
64 {
65 return -std::distance(other.it_, it_);
66 }
67 reverse_iterator & operator+=(diff_t n)
68 {
69 std::advance(it_, -n);
70 return *this;
71 }
72
73 // No need for a using declaration to make
74 // iterator_interface::operator++(int) visible, because we're not defining
75 // operator++() in this template.
76
77private:
78 BidiIter it_;
79};
80
81using rev_bidi_iter = reverse_iterator<std::list<int>::iterator>;
82using rev_ra_iter = reverse_iterator<std::vector<int>::iterator>;
83
84
85int main()
86{
87 {
88 std::list<int> ints = {4, 3, 2};
89 std::list<int> ints_copy;
90 std::copy(
91 first: rev_bidi_iter(ints.end()),
92 last: rev_bidi_iter(ints.begin()),
93 result: std::back_inserter(x&: ints_copy));
94 std::reverse(first: ints.begin(), last: ints.end());
95 assert(ints_copy == ints);
96 }
97
98 {
99 std::vector<int> ints = {4, 3, 2};
100 std::vector<int> ints_copy(ints.size());
101 std::copy(
102 first: rev_ra_iter(ints.end()),
103 last: rev_ra_iter(ints.begin()),
104 result: ints_copy.begin());
105 std::reverse(first: ints.begin(), last: ints.end());
106 assert(ints_copy == ints);
107 }
108
109 {
110 using rev_ptr_iter = reverse_iterator<int *>;
111
112 int ints[3] = {4, 3, 2};
113 int ints_copy[3];
114 std::copy(
115 first: rev_ptr_iter(std::end(arr&: ints)),
116 last: rev_ptr_iter(std::begin(arr&: ints)),
117 result: std::begin(arr&: ints_copy));
118 std::reverse(first: std::begin(arr&: ints), last: std::end(arr&: ints));
119 assert(std::equal(
120 std::begin(ints_copy),
121 std::end(ints_copy),
122 std::begin(ints),
123 std::end(ints)));
124 }
125}
126//]
127

source code of boost/libs/stl_interfaces/example/reverse_iterator.cpp