1 // (C) Copyright Jeremy Siek 2001.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef BOOST_SHADOW_ITERATOR_HPP
7 #define BOOST_SHADOW_ITERATOR_HPP
8
9 #include <boost/iterator_adaptors.hpp>
10 #include <boost/operators.hpp>
11
12 namespace boost
13 {
14
15 namespace detail
16 {
17
18 template < class A, class B, class D >
19 class shadow_proxy : boost::operators< shadow_proxy< A, B, D > >
20 {
21 typedef shadow_proxy self;
22
23 public:
shadow_proxy(A aa,B bb)24 inline shadow_proxy(A aa, B bb) : a(aa), b(bb) {}
shadow_proxy(const self & x)25 inline shadow_proxy(const self& x) : a(x.a), b(x.b) {}
shadow_proxy(Self x)26 template < class Self > inline shadow_proxy(Self x) : a(x.a), b(x.b) {}
operator =(const self & x)27 inline self& operator=(const self& x)
28 {
29 a = x.a;
30 b = x.b;
31 return *this;
32 }
operator ++()33 inline self& operator++()
34 {
35 ++a;
36 return *this;
37 }
operator --()38 inline self& operator--()
39 {
40 --a;
41 return *this;
42 }
operator +=(const self & x)43 inline self& operator+=(const self& x)
44 {
45 a += x.a;
46 return *this;
47 }
operator -=(const self & x)48 inline self& operator-=(const self& x)
49 {
50 a -= x.a;
51 return *this;
52 }
operator *=(const self & x)53 inline self& operator*=(const self& x)
54 {
55 a *= x.a;
56 return *this;
57 }
operator /=(const self & x)58 inline self& operator/=(const self& x)
59 {
60 a /= x.a;
61 return *this;
62 }
operator %=(const self & x)63 inline self& operator%=(const self& x) { return *this; } // JGS
operator &=(const self & x)64 inline self& operator&=(const self& x) { return *this; } // JGS
operator |=(const self & x)65 inline self& operator|=(const self& x) { return *this; } // JGS
operator ^=(const self & x)66 inline self& operator^=(const self& x) { return *this; } // JGS
operator -(const self & x,const self & y)67 inline friend D operator-(const self& x, const self& y)
68 {
69 return x.a - y.a;
70 }
operator ==(const self & x) const71 inline bool operator==(const self& x) const { return a == x.a; }
operator <(const self & x) const72 inline bool operator<(const self& x) const { return a < x.a; }
73 // protected:
74 A a;
75 B b;
76 };
77
78 struct shadow_iterator_policies
79 {
initializeboost::detail::shadow_iterator_policies80 template < typename iter_pair > void initialize(const iter_pair&) {}
81
82 template < typename Iter >
dereferenceboost::detail::shadow_iterator_policies83 typename Iter::reference dereference(const Iter& i) const
84 {
85 typedef typename Iter::reference R;
86 return R(*i.base().first, *i.base().second);
87 }
88 template < typename Iter >
equalboost::detail::shadow_iterator_policies89 bool equal(const Iter& p1, const Iter& p2) const
90 {
91 return p1.base().first == p2.base().first;
92 }
incrementboost::detail::shadow_iterator_policies93 template < typename Iter > void increment(Iter& i)
94 {
95 ++i.base().first;
96 ++i.base().second;
97 }
98
decrementboost::detail::shadow_iterator_policies99 template < typename Iter > void decrement(Iter& i)
100 {
101 --i.base().first;
102 --i.base().second;
103 }
104
lessboost::detail::shadow_iterator_policies105 template < typename Iter > bool less(const Iter& x, const Iter& y) const
106 {
107 return x.base().first < y.base().first;
108 }
109 template < typename Iter >
distanceboost::detail::shadow_iterator_policies110 typename Iter::difference_type distance(
111 const Iter& x, const Iter& y) const
112 {
113 return y.base().first - x.base().first;
114 }
advanceboost::detail::shadow_iterator_policies115 template < typename D, typename Iter > void advance(Iter& p, D n)
116 {
117 p.base().first += n;
118 p.base().second += n;
119 }
120 };
121
122 } // namespace detail
123
124 template < typename IterA, typename IterB > struct shadow_iterator_generator
125 {
126
127 // To use the iterator_adaptor we can't derive from
128 // random_access_iterator because we don't have a real reference.
129 // However, we want the STL algorithms to treat the shadow
130 // iterator like a random access iterator.
131 struct shadow_iterator_tag : public std::input_iterator_tag
132 {
operator std::random_access_iterator_tagboost::shadow_iterator_generator::shadow_iterator_tag133 operator std::random_access_iterator_tag()
134 {
135 return std::random_access_iterator_tag();
136 };
137 };
138 typedef typename std::iterator_traits< IterA >::value_type Aval;
139 typedef typename std::iterator_traits< IterB >::value_type Bval;
140 typedef typename std::iterator_traits< IterA >::reference Aref;
141 typedef typename std::iterator_traits< IterB >::reference Bref;
142 typedef typename std::iterator_traits< IterA >::difference_type D;
143 typedef detail::shadow_proxy< Aval, Bval, Aval > V;
144 typedef detail::shadow_proxy< Aref, Bref, Aval > R;
145 typedef iterator_adaptor< std::pair< IterA, IterB >,
146 detail::shadow_iterator_policies, V, R, V*, shadow_iterator_tag, D >
147 type;
148 };
149
150 // short cut for creating a shadow iterator
151 template < class IterA, class IterB >
152 inline typename shadow_iterator_generator< IterA, IterB >::type
make_shadow_iter(IterA a,IterB b)153 make_shadow_iter(IterA a, IterB b)
154 {
155 typedef typename shadow_iterator_generator< IterA, IterB >::type Iter;
156 return Iter(std::make_pair(a, b));
157 }
158
159 template < class Cmp > struct shadow_cmp
160 {
shadow_cmpboost::shadow_cmp161 inline shadow_cmp(const Cmp& c) : cmp(c) {}
162 template < class ShadowProxy1, class ShadowProxy2 >
operator ()boost::shadow_cmp163 inline bool operator()(const ShadowProxy1& x, const ShadowProxy2& y) const
164 {
165 return cmp(x.a, y.a);
166 }
167 Cmp cmp;
168 };
169
170 } // namespace boost
171
172 namespace std
173 {
174 template < class A1, class B1, class D1, class A2, class B2, class D2 >
swap(boost::detail::shadow_proxy<A1 &,B1 &,D1> x,boost::detail::shadow_proxy<A2 &,B2 &,D2> y)175 void swap(boost::detail::shadow_proxy< A1&, B1&, D1 > x,
176 boost::detail::shadow_proxy< A2&, B2&, D2 > y)
177 {
178 std::swap(x.a, y.a);
179 std::swap(x.b, y.b);
180 }
181 }
182
183 #endif // BOOST_SHADOW_ITERATOR_HPP
184