]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
f67539c2 TL |
12 | namespace boost |
13 | { | |
7c673cae | 14 | |
f67539c2 TL |
15 | namespace detail |
16 | { | |
7c673cae | 17 | |
f67539c2 TL |
18 | template < class A, class B, class D > |
19 | class shadow_proxy : boost::operators< shadow_proxy< A, B, D > > | |
7c673cae | 20 | { |
f67539c2 TL |
21 | typedef shadow_proxy self; |
22 | ||
7c673cae | 23 | public: |
f67539c2 TL |
24 | inline shadow_proxy(A aa, B bb) : a(aa), b(bb) {} |
25 | inline shadow_proxy(const self& x) : a(x.a), b(x.b) {} | |
26 | template < class Self > inline shadow_proxy(Self x) : a(x.a), b(x.b) {} | |
27 | inline self& operator=(const self& x) | |
28 | { | |
29 | a = x.a; | |
30 | b = x.b; | |
31 | return *this; | |
32 | } | |
33 | inline self& operator++() | |
34 | { | |
35 | ++a; | |
36 | return *this; | |
37 | } | |
38 | inline self& operator--() | |
39 | { | |
40 | --a; | |
41 | return *this; | |
42 | } | |
43 | inline self& operator+=(const self& x) | |
44 | { | |
45 | a += x.a; | |
46 | return *this; | |
47 | } | |
48 | inline self& operator-=(const self& x) | |
49 | { | |
50 | a -= x.a; | |
51 | return *this; | |
52 | } | |
53 | inline self& operator*=(const self& x) | |
54 | { | |
55 | a *= x.a; | |
56 | return *this; | |
57 | } | |
58 | inline self& operator/=(const self& x) | |
59 | { | |
60 | a /= x.a; | |
61 | return *this; | |
62 | } | |
63 | inline self& operator%=(const self& x) { return *this; } // JGS | |
64 | inline self& operator&=(const self& x) { return *this; } // JGS | |
65 | inline self& operator|=(const self& x) { return *this; } // JGS | |
66 | inline self& operator^=(const self& x) { return *this; } // JGS | |
67 | inline friend D operator-(const self& x, const self& y) | |
68 | { | |
69 | return x.a - y.a; | |
70 | } | |
71 | inline bool operator==(const self& x) const { return a == x.a; } | |
72 | inline bool operator<(const self& x) const { return a < x.a; } | |
73 | // protected: | |
74 | A a; | |
75 | B b; | |
7c673cae FG |
76 | }; |
77 | ||
78 | struct shadow_iterator_policies | |
79 | { | |
f67539c2 TL |
80 | template < typename iter_pair > void initialize(const iter_pair&) {} |
81 | ||
82 | template < typename Iter > | |
83 | 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 > | |
89 | bool equal(const Iter& p1, const Iter& p2) const | |
90 | { | |
91 | return p1.base().first == p2.base().first; | |
92 | } | |
93 | template < typename Iter > void increment(Iter& i) | |
94 | { | |
95 | ++i.base().first; | |
96 | ++i.base().second; | |
97 | } | |
98 | ||
99 | template < typename Iter > void decrement(Iter& i) | |
100 | { | |
101 | --i.base().first; | |
102 | --i.base().second; | |
103 | } | |
104 | ||
105 | 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 > | |
110 | typename Iter::difference_type distance( | |
111 | const Iter& x, const Iter& y) const | |
112 | { | |
113 | return y.base().first - x.base().first; | |
114 | } | |
115 | template < typename D, typename Iter > void advance(Iter& p, D n) | |
116 | { | |
117 | p.base().first += n; | |
118 | p.base().second += n; | |
119 | } | |
7c673cae FG |
120 | }; |
121 | ||
f67539c2 TL |
122 | } // namespace detail |
123 | ||
124 | template < typename IterA, typename IterB > struct shadow_iterator_generator | |
125 | { | |
7c673cae | 126 | |
7c673cae FG |
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. | |
f67539c2 TL |
131 | struct shadow_iterator_tag : public std::input_iterator_tag |
132 | { | |
133 | operator std::random_access_iterator_tag() | |
134 | { | |
135 | return std::random_access_iterator_tag(); | |
136 | }; | |
7c673cae | 137 | }; |
f67539c2 TL |
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 | |
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 | { | |
161 | inline shadow_cmp(const Cmp& c) : cmp(c) {} | |
162 | template < class ShadowProxy1, class ShadowProxy2 > | |
7c673cae FG |
163 | inline bool operator()(const ShadowProxy1& x, const ShadowProxy2& y) const |
164 | { | |
f67539c2 | 165 | return cmp(x.a, y.a); |
7c673cae FG |
166 | } |
167 | Cmp cmp; | |
f67539c2 | 168 | }; |
7c673cae FG |
169 | |
170 | } // namespace boost | |
171 | ||
f67539c2 TL |
172 | namespace std |
173 | { | |
174 | template < class A1, class B1, class D1, class A2, class B2, class D2 > | |
175 | void swap(boost::detail::shadow_proxy< A1&, B1&, D1 > x, | |
176 | boost::detail::shadow_proxy< A2&, B2&, D2 > y) | |
177 | { | |
7c673cae FG |
178 | std::swap(x.a, y.a); |
179 | std::swap(x.b, y.b); | |
f67539c2 | 180 | } |
7c673cae FG |
181 | } |
182 | ||
183 | #endif // BOOST_SHADOW_ITERATOR_HPP |