1 /* Copyright 2003-2013 Joaquin M Lopez Munoz.
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
6 * See http://www.boost.org/libs/multi_index for library home page.
9 #ifndef BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
10 #define BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
17 #include <boost/mpl/apply.hpp>
18 #include <boost/operators.hpp>
22 namespace multi_index{
26 /* Poor man's version of boost::iterator_adaptor. Used instead of the
27 * original as compile times for the latter are significantly higher.
28 * The interface is not replicated exactly, only to the extent necessary
29 * for internal consumption.
32 /* NB. The purpose of the (non-inclass) global operators ==, < and - defined
33 * above is to partially alleviate a problem of MSVC++ 6.0 by * which
34 * friend-injected operators on T are not visible if T is instantiated only
35 * in template code where T is a dependent type.
38 class iter_adaptor_access
42 static typename Class::reference dereference(const Class& x)
44 return x.dereference();
48 static bool equal(const Class& x,const Class& y)
54 static void increment(Class& x)
60 static void decrement(Class& x)
66 static void advance(Class& x,typename Class::difference_type n)
72 static typename Class::difference_type distance_to(
73 const Class& x,const Class& y)
75 return x.distance_to(y);
79 template<typename Category>
80 struct iter_adaptor_selector;
82 template<class Derived,class Base>
83 class forward_iter_adaptor_base:
84 public forward_iterator_helper<
86 typename Base::value_type,
87 typename Base::difference_type,
88 typename Base::pointer,
89 typename Base::reference>
92 typedef typename Base::reference reference;
94 reference operator*()const
96 return iter_adaptor_access::dereference(final());
99 friend bool operator==(const Derived& x,const Derived& y)
101 return iter_adaptor_access::equal(x,y);
104 Derived& operator++()
106 iter_adaptor_access::increment(final());
111 Derived& final(){return *static_cast<Derived*>(this);}
112 const Derived& final()const{return *static_cast<const Derived*>(this);}
115 template<class Derived,class Base>
117 const forward_iter_adaptor_base<Derived,Base>& x,
118 const forward_iter_adaptor_base<Derived,Base>& y)
120 return iter_adaptor_access::equal(
121 static_cast<const Derived&>(x),static_cast<const Derived&>(y));
125 struct iter_adaptor_selector<std::forward_iterator_tag>
127 template<class Derived,class Base>
130 typedef forward_iter_adaptor_base<Derived,Base> type;
134 template<class Derived,class Base>
135 class bidirectional_iter_adaptor_base:
136 public bidirectional_iterator_helper<
138 typename Base::value_type,
139 typename Base::difference_type,
140 typename Base::pointer,
141 typename Base::reference>
144 typedef typename Base::reference reference;
146 reference operator*()const
148 return iter_adaptor_access::dereference(final());
151 friend bool operator==(const Derived& x,const Derived& y)
153 return iter_adaptor_access::equal(x,y);
156 Derived& operator++()
158 iter_adaptor_access::increment(final());
162 Derived& operator--()
164 iter_adaptor_access::decrement(final());
169 Derived& final(){return *static_cast<Derived*>(this);}
170 const Derived& final()const{return *static_cast<const Derived*>(this);}
173 template<class Derived,class Base>
175 const bidirectional_iter_adaptor_base<Derived,Base>& x,
176 const bidirectional_iter_adaptor_base<Derived,Base>& y)
178 return iter_adaptor_access::equal(
179 static_cast<const Derived&>(x),static_cast<const Derived&>(y));
183 struct iter_adaptor_selector<std::bidirectional_iterator_tag>
185 template<class Derived,class Base>
188 typedef bidirectional_iter_adaptor_base<Derived,Base> type;
192 template<class Derived,class Base>
193 class random_access_iter_adaptor_base:
194 public random_access_iterator_helper<
196 typename Base::value_type,
197 typename Base::difference_type,
198 typename Base::pointer,
199 typename Base::reference>
202 typedef typename Base::reference reference;
203 typedef typename Base::difference_type difference_type;
205 reference operator*()const
207 return iter_adaptor_access::dereference(final());
210 friend bool operator==(const Derived& x,const Derived& y)
212 return iter_adaptor_access::equal(x,y);
215 friend bool operator<(const Derived& x,const Derived& y)
217 return iter_adaptor_access::distance_to(x,y)>0;
220 Derived& operator++()
222 iter_adaptor_access::increment(final());
226 Derived& operator--()
228 iter_adaptor_access::decrement(final());
232 Derived& operator+=(difference_type n)
234 iter_adaptor_access::advance(final(),n);
238 Derived& operator-=(difference_type n)
240 iter_adaptor_access::advance(final(),-n);
244 friend difference_type operator-(const Derived& x,const Derived& y)
246 return iter_adaptor_access::distance_to(y,x);
250 Derived& final(){return *static_cast<Derived*>(this);}
251 const Derived& final()const{return *static_cast<const Derived*>(this);}
254 template<class Derived,class Base>
256 const random_access_iter_adaptor_base<Derived,Base>& x,
257 const random_access_iter_adaptor_base<Derived,Base>& y)
259 return iter_adaptor_access::equal(
260 static_cast<const Derived&>(x),static_cast<const Derived&>(y));
263 template<class Derived,class Base>
265 const random_access_iter_adaptor_base<Derived,Base>& x,
266 const random_access_iter_adaptor_base<Derived,Base>& y)
268 return iter_adaptor_access::distance_to(
269 static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0;
272 template<class Derived,class Base>
273 typename random_access_iter_adaptor_base<Derived,Base>::difference_type
275 const random_access_iter_adaptor_base<Derived,Base>& x,
276 const random_access_iter_adaptor_base<Derived,Base>& y)
278 return iter_adaptor_access::distance_to(
279 static_cast<const Derived&>(y),static_cast<const Derived&>(x));
283 struct iter_adaptor_selector<std::random_access_iterator_tag>
285 template<class Derived,class Base>
288 typedef random_access_iter_adaptor_base<Derived,Base> type;
292 template<class Derived,class Base>
293 struct iter_adaptor_base
295 typedef iter_adaptor_selector<
296 typename Base::iterator_category> selector;
297 typedef typename mpl::apply2<
298 selector,Derived,Base>::type type;
301 template<class Derived,class Base>
302 class iter_adaptor:public iter_adaptor_base<Derived,Base>::type
306 explicit iter_adaptor(const Base& b_):b(b_){}
308 const Base& base_reference()const{return b;}
309 Base& base_reference(){return b;}
315 } /* namespace multi_index::detail */
317 } /* namespace multi_index */
319 } /* namespace boost */