Chris@101
|
1 /* Copyright 2003-2013 Joaquin M Lopez Munoz.
|
Chris@16
|
2 * Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
3 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5 *
|
Chris@16
|
6 * See http://www.boost.org/libs/multi_index for library home page.
|
Chris@16
|
7 */
|
Chris@16
|
8
|
Chris@16
|
9 #ifndef BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
|
Chris@16
|
10 #define BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
|
Chris@16
|
11
|
Chris@101
|
12 #if defined(_MSC_VER)
|
Chris@16
|
13 #pragma once
|
Chris@16
|
14 #endif
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
Chris@16
|
17 #include <boost/mpl/apply.hpp>
|
Chris@16
|
18 #include <boost/operators.hpp>
|
Chris@16
|
19
|
Chris@16
|
20 namespace boost{
|
Chris@16
|
21
|
Chris@16
|
22 namespace multi_index{
|
Chris@16
|
23
|
Chris@16
|
24 namespace detail{
|
Chris@16
|
25
|
Chris@16
|
26 /* Poor man's version of boost::iterator_adaptor. Used instead of the
|
Chris@16
|
27 * original as compile times for the latter are significantly higher.
|
Chris@16
|
28 * The interface is not replicated exactly, only to the extent necessary
|
Chris@16
|
29 * for internal consumption.
|
Chris@16
|
30 */
|
Chris@16
|
31
|
Chris@16
|
32 /* NB. The purpose of the (non-inclass) global operators ==, < and - defined
|
Chris@16
|
33 * above is to partially alleviate a problem of MSVC++ 6.0 by * which
|
Chris@16
|
34 * friend-injected operators on T are not visible if T is instantiated only
|
Chris@16
|
35 * in template code where T is a dependent type.
|
Chris@16
|
36 */
|
Chris@16
|
37
|
Chris@16
|
38 class iter_adaptor_access
|
Chris@16
|
39 {
|
Chris@16
|
40 public:
|
Chris@16
|
41 template<class Class>
|
Chris@16
|
42 static typename Class::reference dereference(const Class& x)
|
Chris@16
|
43 {
|
Chris@16
|
44 return x.dereference();
|
Chris@16
|
45 }
|
Chris@16
|
46
|
Chris@16
|
47 template<class Class>
|
Chris@16
|
48 static bool equal(const Class& x,const Class& y)
|
Chris@16
|
49 {
|
Chris@16
|
50 return x.equal(y);
|
Chris@16
|
51 }
|
Chris@16
|
52
|
Chris@16
|
53 template<class Class>
|
Chris@16
|
54 static void increment(Class& x)
|
Chris@16
|
55 {
|
Chris@16
|
56 x.increment();
|
Chris@16
|
57 }
|
Chris@16
|
58
|
Chris@16
|
59 template<class Class>
|
Chris@16
|
60 static void decrement(Class& x)
|
Chris@16
|
61 {
|
Chris@16
|
62 x.decrement();
|
Chris@16
|
63 }
|
Chris@16
|
64
|
Chris@16
|
65 template<class Class>
|
Chris@16
|
66 static void advance(Class& x,typename Class::difference_type n)
|
Chris@16
|
67 {
|
Chris@16
|
68 x.advance(n);
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 template<class Class>
|
Chris@16
|
72 static typename Class::difference_type distance_to(
|
Chris@16
|
73 const Class& x,const Class& y)
|
Chris@16
|
74 {
|
Chris@16
|
75 return x.distance_to(y);
|
Chris@16
|
76 }
|
Chris@16
|
77 };
|
Chris@16
|
78
|
Chris@16
|
79 template<typename Category>
|
Chris@16
|
80 struct iter_adaptor_selector;
|
Chris@16
|
81
|
Chris@16
|
82 template<class Derived,class Base>
|
Chris@16
|
83 class forward_iter_adaptor_base:
|
Chris@16
|
84 public forward_iterator_helper<
|
Chris@16
|
85 Derived,
|
Chris@16
|
86 typename Base::value_type,
|
Chris@16
|
87 typename Base::difference_type,
|
Chris@16
|
88 typename Base::pointer,
|
Chris@16
|
89 typename Base::reference>
|
Chris@16
|
90 {
|
Chris@16
|
91 public:
|
Chris@16
|
92 typedef typename Base::reference reference;
|
Chris@16
|
93
|
Chris@16
|
94 reference operator*()const
|
Chris@16
|
95 {
|
Chris@16
|
96 return iter_adaptor_access::dereference(final());
|
Chris@16
|
97 }
|
Chris@16
|
98
|
Chris@16
|
99 friend bool operator==(const Derived& x,const Derived& y)
|
Chris@16
|
100 {
|
Chris@16
|
101 return iter_adaptor_access::equal(x,y);
|
Chris@16
|
102 }
|
Chris@16
|
103
|
Chris@16
|
104 Derived& operator++()
|
Chris@16
|
105 {
|
Chris@16
|
106 iter_adaptor_access::increment(final());
|
Chris@16
|
107 return final();
|
Chris@16
|
108 }
|
Chris@16
|
109
|
Chris@16
|
110 private:
|
Chris@16
|
111 Derived& final(){return *static_cast<Derived*>(this);}
|
Chris@16
|
112 const Derived& final()const{return *static_cast<const Derived*>(this);}
|
Chris@16
|
113 };
|
Chris@16
|
114
|
Chris@16
|
115 template<class Derived,class Base>
|
Chris@16
|
116 bool operator==(
|
Chris@16
|
117 const forward_iter_adaptor_base<Derived,Base>& x,
|
Chris@16
|
118 const forward_iter_adaptor_base<Derived,Base>& y)
|
Chris@16
|
119 {
|
Chris@16
|
120 return iter_adaptor_access::equal(
|
Chris@16
|
121 static_cast<const Derived&>(x),static_cast<const Derived&>(y));
|
Chris@16
|
122 }
|
Chris@16
|
123
|
Chris@16
|
124 template<>
|
Chris@16
|
125 struct iter_adaptor_selector<std::forward_iterator_tag>
|
Chris@16
|
126 {
|
Chris@16
|
127 template<class Derived,class Base>
|
Chris@16
|
128 struct apply
|
Chris@16
|
129 {
|
Chris@16
|
130 typedef forward_iter_adaptor_base<Derived,Base> type;
|
Chris@16
|
131 };
|
Chris@16
|
132 };
|
Chris@16
|
133
|
Chris@16
|
134 template<class Derived,class Base>
|
Chris@16
|
135 class bidirectional_iter_adaptor_base:
|
Chris@16
|
136 public bidirectional_iterator_helper<
|
Chris@16
|
137 Derived,
|
Chris@16
|
138 typename Base::value_type,
|
Chris@16
|
139 typename Base::difference_type,
|
Chris@16
|
140 typename Base::pointer,
|
Chris@16
|
141 typename Base::reference>
|
Chris@16
|
142 {
|
Chris@16
|
143 public:
|
Chris@16
|
144 typedef typename Base::reference reference;
|
Chris@16
|
145
|
Chris@16
|
146 reference operator*()const
|
Chris@16
|
147 {
|
Chris@16
|
148 return iter_adaptor_access::dereference(final());
|
Chris@16
|
149 }
|
Chris@16
|
150
|
Chris@16
|
151 friend bool operator==(const Derived& x,const Derived& y)
|
Chris@16
|
152 {
|
Chris@16
|
153 return iter_adaptor_access::equal(x,y);
|
Chris@16
|
154 }
|
Chris@16
|
155
|
Chris@16
|
156 Derived& operator++()
|
Chris@16
|
157 {
|
Chris@16
|
158 iter_adaptor_access::increment(final());
|
Chris@16
|
159 return final();
|
Chris@16
|
160 }
|
Chris@16
|
161
|
Chris@16
|
162 Derived& operator--()
|
Chris@16
|
163 {
|
Chris@16
|
164 iter_adaptor_access::decrement(final());
|
Chris@16
|
165 return final();
|
Chris@16
|
166 }
|
Chris@16
|
167
|
Chris@16
|
168 private:
|
Chris@16
|
169 Derived& final(){return *static_cast<Derived*>(this);}
|
Chris@16
|
170 const Derived& final()const{return *static_cast<const Derived*>(this);}
|
Chris@16
|
171 };
|
Chris@16
|
172
|
Chris@16
|
173 template<class Derived,class Base>
|
Chris@16
|
174 bool operator==(
|
Chris@16
|
175 const bidirectional_iter_adaptor_base<Derived,Base>& x,
|
Chris@16
|
176 const bidirectional_iter_adaptor_base<Derived,Base>& y)
|
Chris@16
|
177 {
|
Chris@16
|
178 return iter_adaptor_access::equal(
|
Chris@16
|
179 static_cast<const Derived&>(x),static_cast<const Derived&>(y));
|
Chris@16
|
180 }
|
Chris@16
|
181
|
Chris@16
|
182 template<>
|
Chris@16
|
183 struct iter_adaptor_selector<std::bidirectional_iterator_tag>
|
Chris@16
|
184 {
|
Chris@16
|
185 template<class Derived,class Base>
|
Chris@16
|
186 struct apply
|
Chris@16
|
187 {
|
Chris@16
|
188 typedef bidirectional_iter_adaptor_base<Derived,Base> type;
|
Chris@16
|
189 };
|
Chris@16
|
190 };
|
Chris@16
|
191
|
Chris@16
|
192 template<class Derived,class Base>
|
Chris@16
|
193 class random_access_iter_adaptor_base:
|
Chris@16
|
194 public random_access_iterator_helper<
|
Chris@16
|
195 Derived,
|
Chris@16
|
196 typename Base::value_type,
|
Chris@16
|
197 typename Base::difference_type,
|
Chris@16
|
198 typename Base::pointer,
|
Chris@16
|
199 typename Base::reference>
|
Chris@16
|
200 {
|
Chris@16
|
201 public:
|
Chris@16
|
202 typedef typename Base::reference reference;
|
Chris@16
|
203 typedef typename Base::difference_type difference_type;
|
Chris@16
|
204
|
Chris@16
|
205 reference operator*()const
|
Chris@16
|
206 {
|
Chris@16
|
207 return iter_adaptor_access::dereference(final());
|
Chris@16
|
208 }
|
Chris@16
|
209
|
Chris@16
|
210 friend bool operator==(const Derived& x,const Derived& y)
|
Chris@16
|
211 {
|
Chris@16
|
212 return iter_adaptor_access::equal(x,y);
|
Chris@16
|
213 }
|
Chris@16
|
214
|
Chris@16
|
215 friend bool operator<(const Derived& x,const Derived& y)
|
Chris@16
|
216 {
|
Chris@16
|
217 return iter_adaptor_access::distance_to(x,y)>0;
|
Chris@16
|
218 }
|
Chris@16
|
219
|
Chris@16
|
220 Derived& operator++()
|
Chris@16
|
221 {
|
Chris@16
|
222 iter_adaptor_access::increment(final());
|
Chris@16
|
223 return final();
|
Chris@16
|
224 }
|
Chris@16
|
225
|
Chris@16
|
226 Derived& operator--()
|
Chris@16
|
227 {
|
Chris@16
|
228 iter_adaptor_access::decrement(final());
|
Chris@16
|
229 return final();
|
Chris@16
|
230 }
|
Chris@16
|
231
|
Chris@16
|
232 Derived& operator+=(difference_type n)
|
Chris@16
|
233 {
|
Chris@16
|
234 iter_adaptor_access::advance(final(),n);
|
Chris@16
|
235 return final();
|
Chris@16
|
236 }
|
Chris@16
|
237
|
Chris@16
|
238 Derived& operator-=(difference_type n)
|
Chris@16
|
239 {
|
Chris@16
|
240 iter_adaptor_access::advance(final(),-n);
|
Chris@16
|
241 return final();
|
Chris@16
|
242 }
|
Chris@16
|
243
|
Chris@16
|
244 friend difference_type operator-(const Derived& x,const Derived& y)
|
Chris@16
|
245 {
|
Chris@16
|
246 return iter_adaptor_access::distance_to(y,x);
|
Chris@16
|
247 }
|
Chris@16
|
248
|
Chris@16
|
249 private:
|
Chris@16
|
250 Derived& final(){return *static_cast<Derived*>(this);}
|
Chris@16
|
251 const Derived& final()const{return *static_cast<const Derived*>(this);}
|
Chris@16
|
252 };
|
Chris@16
|
253
|
Chris@16
|
254 template<class Derived,class Base>
|
Chris@16
|
255 bool operator==(
|
Chris@16
|
256 const random_access_iter_adaptor_base<Derived,Base>& x,
|
Chris@16
|
257 const random_access_iter_adaptor_base<Derived,Base>& y)
|
Chris@16
|
258 {
|
Chris@16
|
259 return iter_adaptor_access::equal(
|
Chris@16
|
260 static_cast<const Derived&>(x),static_cast<const Derived&>(y));
|
Chris@16
|
261 }
|
Chris@16
|
262
|
Chris@16
|
263 template<class Derived,class Base>
|
Chris@16
|
264 bool operator<(
|
Chris@16
|
265 const random_access_iter_adaptor_base<Derived,Base>& x,
|
Chris@16
|
266 const random_access_iter_adaptor_base<Derived,Base>& y)
|
Chris@16
|
267 {
|
Chris@16
|
268 return iter_adaptor_access::distance_to(
|
Chris@16
|
269 static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0;
|
Chris@16
|
270 }
|
Chris@16
|
271
|
Chris@16
|
272 template<class Derived,class Base>
|
Chris@16
|
273 typename random_access_iter_adaptor_base<Derived,Base>::difference_type
|
Chris@16
|
274 operator-(
|
Chris@16
|
275 const random_access_iter_adaptor_base<Derived,Base>& x,
|
Chris@16
|
276 const random_access_iter_adaptor_base<Derived,Base>& y)
|
Chris@16
|
277 {
|
Chris@16
|
278 return iter_adaptor_access::distance_to(
|
Chris@16
|
279 static_cast<const Derived&>(y),static_cast<const Derived&>(x));
|
Chris@16
|
280 }
|
Chris@16
|
281
|
Chris@16
|
282 template<>
|
Chris@16
|
283 struct iter_adaptor_selector<std::random_access_iterator_tag>
|
Chris@16
|
284 {
|
Chris@16
|
285 template<class Derived,class Base>
|
Chris@16
|
286 struct apply
|
Chris@16
|
287 {
|
Chris@16
|
288 typedef random_access_iter_adaptor_base<Derived,Base> type;
|
Chris@16
|
289 };
|
Chris@16
|
290 };
|
Chris@16
|
291
|
Chris@16
|
292 template<class Derived,class Base>
|
Chris@16
|
293 struct iter_adaptor_base
|
Chris@16
|
294 {
|
Chris@16
|
295 typedef iter_adaptor_selector<
|
Chris@101
|
296 typename Base::iterator_category> selector;
|
Chris@101
|
297 typedef typename mpl::apply2<
|
Chris@101
|
298 selector,Derived,Base>::type type;
|
Chris@16
|
299 };
|
Chris@16
|
300
|
Chris@16
|
301 template<class Derived,class Base>
|
Chris@16
|
302 class iter_adaptor:public iter_adaptor_base<Derived,Base>::type
|
Chris@16
|
303 {
|
Chris@16
|
304 protected:
|
Chris@16
|
305 iter_adaptor(){}
|
Chris@16
|
306 explicit iter_adaptor(const Base& b_):b(b_){}
|
Chris@16
|
307
|
Chris@16
|
308 const Base& base_reference()const{return b;}
|
Chris@16
|
309 Base& base_reference(){return b;}
|
Chris@16
|
310
|
Chris@16
|
311 private:
|
Chris@16
|
312 Base b;
|
Chris@16
|
313 };
|
Chris@16
|
314
|
Chris@16
|
315 } /* namespace multi_index::detail */
|
Chris@16
|
316
|
Chris@16
|
317 } /* namespace multi_index */
|
Chris@16
|
318
|
Chris@16
|
319 } /* namespace boost */
|
Chris@16
|
320
|
Chris@16
|
321 #endif
|