• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
5  *
6  * See http://www.boost.org/libs/multi_index for library home page.
7  */
8 
9 #ifndef BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
10 #define BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
11 
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15 
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>
19 
20 namespace boost{
21 
22 namespace multi_index{
23 
24 namespace detail{
25 
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.
30  */
31 
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.
36  */
37 
38 class iter_adaptor_access
39 {
40 public:
41   template<class Class>
dereference(const Class & x)42     static typename Class::reference dereference(const Class& x)
43   {
44     return x.dereference();
45   }
46 
47   template<class Class>
equal(const Class & x,const Class & y)48   static bool equal(const Class& x,const Class& y)
49   {
50     return x.equal(y);
51   }
52 
53   template<class Class>
increment(Class & x)54   static void increment(Class& x)
55   {
56     x.increment();
57   }
58 
59   template<class Class>
decrement(Class & x)60   static void decrement(Class& x)
61   {
62     x.decrement();
63   }
64 
65   template<class Class>
advance(Class & x,typename Class::difference_type n)66   static void advance(Class& x,typename Class::difference_type n)
67   {
68     x.advance(n);
69   }
70 
71   template<class Class>
distance_to(const Class & x,const Class & y)72   static typename Class::difference_type distance_to(
73     const Class& x,const Class& y)
74   {
75     return x.distance_to(y);
76   }
77 };
78 
79 template<typename Category>
80 struct iter_adaptor_selector;
81 
82 template<class Derived,class Base>
83 class forward_iter_adaptor_base:
84   public forward_iterator_helper<
85     Derived,
86     typename Base::value_type,
87     typename Base::difference_type,
88     typename Base::pointer,
89     typename Base::reference>
90 {
91 public:
92   typedef typename Base::reference reference;
93 
operator *() const94   reference operator*()const
95   {
96     return iter_adaptor_access::dereference(final());
97   }
98 
operator ==(const Derived & x,const Derived & y)99   friend bool operator==(const Derived& x,const Derived& y)
100   {
101     return iter_adaptor_access::equal(x,y);
102   }
103 
operator ++()104   Derived& operator++()
105   {
106     iter_adaptor_access::increment(final());
107     return final();
108   }
109 
110 private:
final()111   Derived& final(){return *static_cast<Derived*>(this);}
final() const112   const Derived& final()const{return *static_cast<const Derived*>(this);}
113 };
114 
115 template<class Derived,class Base>
operator ==(const forward_iter_adaptor_base<Derived,Base> & x,const forward_iter_adaptor_base<Derived,Base> & y)116 bool operator==(
117   const forward_iter_adaptor_base<Derived,Base>& x,
118   const forward_iter_adaptor_base<Derived,Base>& y)
119 {
120   return iter_adaptor_access::equal(
121     static_cast<const Derived&>(x),static_cast<const Derived&>(y));
122 }
123 
124 template<>
125 struct iter_adaptor_selector<std::forward_iterator_tag>
126 {
127   template<class Derived,class Base>
128   struct apply
129   {
130     typedef forward_iter_adaptor_base<Derived,Base> type;
131   };
132 };
133 
134 template<class Derived,class Base>
135 class bidirectional_iter_adaptor_base:
136   public bidirectional_iterator_helper<
137     Derived,
138     typename Base::value_type,
139     typename Base::difference_type,
140     typename Base::pointer,
141     typename Base::reference>
142 {
143 public:
144   typedef typename Base::reference reference;
145 
operator *() const146   reference operator*()const
147   {
148     return iter_adaptor_access::dereference(final());
149   }
150 
operator ==(const Derived & x,const Derived & y)151   friend bool operator==(const Derived& x,const Derived& y)
152   {
153     return iter_adaptor_access::equal(x,y);
154   }
155 
operator ++()156   Derived& operator++()
157   {
158     iter_adaptor_access::increment(final());
159     return final();
160   }
161 
operator --()162   Derived& operator--()
163   {
164     iter_adaptor_access::decrement(final());
165     return final();
166   }
167 
168 private:
final()169   Derived& final(){return *static_cast<Derived*>(this);}
final() const170   const Derived& final()const{return *static_cast<const Derived*>(this);}
171 };
172 
173 template<class Derived,class Base>
operator ==(const bidirectional_iter_adaptor_base<Derived,Base> & x,const bidirectional_iter_adaptor_base<Derived,Base> & y)174 bool operator==(
175   const bidirectional_iter_adaptor_base<Derived,Base>& x,
176   const bidirectional_iter_adaptor_base<Derived,Base>& y)
177 {
178   return iter_adaptor_access::equal(
179     static_cast<const Derived&>(x),static_cast<const Derived&>(y));
180 }
181 
182 template<>
183 struct iter_adaptor_selector<std::bidirectional_iterator_tag>
184 {
185   template<class Derived,class Base>
186   struct apply
187   {
188     typedef bidirectional_iter_adaptor_base<Derived,Base> type;
189   };
190 };
191 
192 template<class Derived,class Base>
193 class random_access_iter_adaptor_base:
194   public random_access_iterator_helper<
195     Derived,
196     typename Base::value_type,
197     typename Base::difference_type,
198     typename Base::pointer,
199     typename Base::reference>
200 {
201 public:
202   typedef typename Base::reference       reference;
203   typedef typename Base::difference_type difference_type;
204 
operator *() const205   reference operator*()const
206   {
207     return iter_adaptor_access::dereference(final());
208   }
209 
operator ==(const Derived & x,const Derived & y)210   friend bool operator==(const Derived& x,const Derived& y)
211   {
212     return iter_adaptor_access::equal(x,y);
213   }
214 
operator <(const Derived & x,const Derived & y)215   friend bool operator<(const Derived& x,const Derived& y)
216   {
217     return iter_adaptor_access::distance_to(x,y)>0;
218   }
219 
operator ++()220   Derived& operator++()
221   {
222     iter_adaptor_access::increment(final());
223     return final();
224   }
225 
operator --()226   Derived& operator--()
227   {
228     iter_adaptor_access::decrement(final());
229     return final();
230   }
231 
operator +=(difference_type n)232   Derived& operator+=(difference_type n)
233   {
234     iter_adaptor_access::advance(final(),n);
235     return final();
236   }
237 
operator -=(difference_type n)238   Derived& operator-=(difference_type n)
239   {
240     iter_adaptor_access::advance(final(),-n);
241     return final();
242   }
243 
operator -(const Derived & x,const Derived & y)244   friend difference_type operator-(const Derived& x,const Derived& y)
245   {
246     return iter_adaptor_access::distance_to(y,x);
247   }
248 
249 private:
final()250   Derived& final(){return *static_cast<Derived*>(this);}
final() const251   const Derived& final()const{return *static_cast<const Derived*>(this);}
252 };
253 
254 template<class Derived,class Base>
operator ==(const random_access_iter_adaptor_base<Derived,Base> & x,const random_access_iter_adaptor_base<Derived,Base> & y)255 bool operator==(
256   const random_access_iter_adaptor_base<Derived,Base>& x,
257   const random_access_iter_adaptor_base<Derived,Base>& y)
258 {
259   return iter_adaptor_access::equal(
260     static_cast<const Derived&>(x),static_cast<const Derived&>(y));
261 }
262 
263 template<class Derived,class Base>
operator <(const random_access_iter_adaptor_base<Derived,Base> & x,const random_access_iter_adaptor_base<Derived,Base> & y)264 bool operator<(
265   const random_access_iter_adaptor_base<Derived,Base>& x,
266   const random_access_iter_adaptor_base<Derived,Base>& y)
267 {
268   return iter_adaptor_access::distance_to(
269     static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0;
270 }
271 
272 template<class Derived,class Base>
273 typename random_access_iter_adaptor_base<Derived,Base>::difference_type
operator -(const random_access_iter_adaptor_base<Derived,Base> & x,const random_access_iter_adaptor_base<Derived,Base> & y)274 operator-(
275   const random_access_iter_adaptor_base<Derived,Base>& x,
276   const random_access_iter_adaptor_base<Derived,Base>& y)
277 {
278   return iter_adaptor_access::distance_to(
279     static_cast<const Derived&>(y),static_cast<const Derived&>(x));
280 }
281 
282 template<>
283 struct iter_adaptor_selector<std::random_access_iterator_tag>
284 {
285   template<class Derived,class Base>
286   struct apply
287   {
288     typedef random_access_iter_adaptor_base<Derived,Base> type;
289   };
290 };
291 
292 template<class Derived,class Base>
293 struct iter_adaptor_base
294 {
295   typedef iter_adaptor_selector<
296     typename Base::iterator_category> selector;
297   typedef typename mpl::apply2<
298     selector,Derived,Base>::type      type;
299 };
300 
301 template<class Derived,class Base>
302 class iter_adaptor:public iter_adaptor_base<Derived,Base>::type
303 {
304 protected:
iter_adaptor()305   iter_adaptor(){}
iter_adaptor(const Base & b_)306   explicit iter_adaptor(const Base& b_):b(b_){}
307 
base_reference() const308   const Base& base_reference()const{return b;}
base_reference()309   Base&       base_reference(){return b;}
310 
311 private:
312   Base b;
313 };
314 
315 } /* namespace multi_index::detail */
316 
317 } /* namespace multi_index */
318 
319 } /* namespace boost */
320 
321 #endif
322