Chris@16
|
1 // Boost.Range library
|
Chris@16
|
2 //
|
Chris@16
|
3 // Copyright Neil Groves 2010. Use, modification and
|
Chris@16
|
4 // distribution is subject to the Boost Software License, Version
|
Chris@16
|
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 //
|
Chris@16
|
8 // For more information, see http://www.boost.org/libs/range/
|
Chris@16
|
9 //
|
Chris@16
|
10 #ifndef BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED
|
Chris@16
|
11 #define BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED
|
Chris@16
|
12
|
Chris@16
|
13 #include <boost/mpl/and.hpp>
|
Chris@16
|
14 #include <boost/mpl/or.hpp>
|
Chris@16
|
15 #include <boost/mpl/not.hpp>
|
Chris@16
|
16 #include <boost/iterator/iterator_facade.hpp>
|
Chris@16
|
17 #include <boost/type_traits/is_const.hpp>
|
Chris@16
|
18 #include <boost/type_traits/is_reference.hpp>
|
Chris@16
|
19 #include <boost/type_traits/remove_reference.hpp>
|
Chris@16
|
20 #include <boost/range/detail/any_iterator_buffer.hpp>
|
Chris@16
|
21 #include <boost/range/detail/any_iterator_interface.hpp>
|
Chris@16
|
22 #include <boost/range/detail/any_iterator_wrapper.hpp>
|
Chris@16
|
23 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 namespace boost
|
Chris@16
|
26 {
|
Chris@16
|
27 namespace range_detail
|
Chris@16
|
28 {
|
Chris@16
|
29 // metafunction to determine if T is a const reference
|
Chris@16
|
30 template<class T>
|
Chris@16
|
31 struct is_const_reference
|
Chris@16
|
32 {
|
Chris@16
|
33 typedef typename mpl::and_<
|
Chris@16
|
34 typename is_reference<T>::type,
|
Chris@16
|
35 typename is_const<
|
Chris@16
|
36 typename remove_reference<T>::type
|
Chris@16
|
37 >::type
|
Chris@16
|
38 >::type type;
|
Chris@16
|
39 };
|
Chris@16
|
40
|
Chris@16
|
41 // metafunction to determine if T is a mutable reference
|
Chris@16
|
42 template<class T>
|
Chris@16
|
43 struct is_mutable_reference
|
Chris@16
|
44 {
|
Chris@16
|
45 typedef typename mpl::and_<
|
Chris@16
|
46 typename is_reference<T>::type,
|
Chris@16
|
47 typename mpl::not_<
|
Chris@16
|
48 typename is_const<
|
Chris@16
|
49 typename remove_reference<T>::type
|
Chris@16
|
50 >::type
|
Chris@16
|
51 >::type
|
Chris@16
|
52 >::type type;
|
Chris@16
|
53 };
|
Chris@16
|
54
|
Chris@16
|
55 // metafunction to evaluate if a source 'reference' can be
|
Chris@16
|
56 // converted to a target 'reference' as a value.
|
Chris@16
|
57 //
|
Chris@16
|
58 // This is true, when the target reference type is actually
|
Chris@16
|
59 // not a reference, and the source reference is convertible
|
Chris@16
|
60 // to the target type.
|
Chris@16
|
61 template<class SourceReference, class TargetReference>
|
Chris@16
|
62 struct is_convertible_to_value_as_reference
|
Chris@16
|
63 {
|
Chris@16
|
64 typedef typename mpl::and_<
|
Chris@16
|
65 typename mpl::not_<
|
Chris@16
|
66 typename is_reference<TargetReference>::type
|
Chris@16
|
67 >::type
|
Chris@16
|
68 , typename is_convertible<
|
Chris@16
|
69 SourceReference
|
Chris@16
|
70 , TargetReference
|
Chris@16
|
71 >::type
|
Chris@16
|
72 >::type type;
|
Chris@16
|
73 };
|
Chris@16
|
74
|
Chris@16
|
75 template<
|
Chris@16
|
76 class Value
|
Chris@16
|
77 , class Traversal
|
Chris@16
|
78 , class Reference
|
Chris@16
|
79 , class Difference
|
Chris@16
|
80 , class Buffer = any_iterator_default_buffer
|
Chris@16
|
81 >
|
Chris@16
|
82 class any_iterator;
|
Chris@16
|
83
|
Chris@16
|
84 // metafunction to determine if SomeIterator is an
|
Chris@16
|
85 // any_iterator.
|
Chris@16
|
86 //
|
Chris@16
|
87 // This is the general implementation which evaluates to false.
|
Chris@16
|
88 template<class SomeIterator>
|
Chris@16
|
89 struct is_any_iterator
|
Chris@16
|
90 : mpl::bool_<false>
|
Chris@16
|
91 {
|
Chris@16
|
92 };
|
Chris@16
|
93
|
Chris@16
|
94 // specialization of is_any_iterator to return true for
|
Chris@16
|
95 // any_iterator classes regardless of template parameters.
|
Chris@16
|
96 template<
|
Chris@16
|
97 class Value
|
Chris@16
|
98 , class Traversal
|
Chris@16
|
99 , class Reference
|
Chris@16
|
100 , class Difference
|
Chris@16
|
101 , class Buffer
|
Chris@16
|
102 >
|
Chris@16
|
103 struct is_any_iterator<
|
Chris@16
|
104 any_iterator<
|
Chris@16
|
105 Value
|
Chris@16
|
106 , Traversal
|
Chris@16
|
107 , Reference
|
Chris@16
|
108 , Difference
|
Chris@16
|
109 , Buffer
|
Chris@16
|
110 >
|
Chris@16
|
111 >
|
Chris@16
|
112 : mpl::bool_<true>
|
Chris@16
|
113 {
|
Chris@16
|
114 };
|
Chris@16
|
115 } // namespace range_detail
|
Chris@16
|
116
|
Chris@101
|
117 namespace iterators
|
Chris@101
|
118 {
|
Chris@16
|
119 namespace detail
|
Chris@16
|
120 {
|
Chris@16
|
121 // Rationale:
|
Chris@16
|
122 // These are specialized since the iterator_facade versions lack
|
Chris@16
|
123 // the requisite typedefs to allow wrapping to determine the types
|
Chris@16
|
124 // if a user copy constructs from a postfix increment.
|
Chris@16
|
125
|
Chris@16
|
126 template<
|
Chris@16
|
127 class Value
|
Chris@16
|
128 , class Traversal
|
Chris@16
|
129 , class Reference
|
Chris@16
|
130 , class Difference
|
Chris@16
|
131 , class Buffer
|
Chris@16
|
132 >
|
Chris@16
|
133 class postfix_increment_proxy<
|
Chris@16
|
134 range_detail::any_iterator<
|
Chris@16
|
135 Value
|
Chris@16
|
136 , Traversal
|
Chris@16
|
137 , Reference
|
Chris@16
|
138 , Difference
|
Chris@16
|
139 , Buffer
|
Chris@16
|
140 >
|
Chris@16
|
141 >
|
Chris@16
|
142 {
|
Chris@16
|
143 typedef range_detail::any_iterator<
|
Chris@16
|
144 Value
|
Chris@16
|
145 , Traversal
|
Chris@16
|
146 , Reference
|
Chris@16
|
147 , Difference
|
Chris@16
|
148 , Buffer
|
Chris@16
|
149 > any_iterator_type;
|
Chris@16
|
150
|
Chris@16
|
151 public:
|
Chris@16
|
152 typedef Value value_type;
|
Chris@16
|
153 typedef typename std::iterator_traits<any_iterator_type>::iterator_category iterator_category;
|
Chris@16
|
154 typedef Difference difference_type;
|
Chris@16
|
155 typedef typename iterator_pointer<any_iterator_type>::type pointer;
|
Chris@16
|
156 typedef Reference reference;
|
Chris@16
|
157
|
Chris@16
|
158 explicit postfix_increment_proxy(any_iterator_type const& x)
|
Chris@16
|
159 : stored_value(*x)
|
Chris@16
|
160 {}
|
Chris@16
|
161
|
Chris@16
|
162 value_type&
|
Chris@16
|
163 operator*() const
|
Chris@16
|
164 {
|
Chris@16
|
165 return this->stored_value;
|
Chris@16
|
166 }
|
Chris@16
|
167 private:
|
Chris@16
|
168 mutable value_type stored_value;
|
Chris@16
|
169 };
|
Chris@16
|
170
|
Chris@16
|
171 template<
|
Chris@16
|
172 class Value
|
Chris@16
|
173 , class Traversal
|
Chris@16
|
174 , class Reference
|
Chris@16
|
175 , class Difference
|
Chris@16
|
176 , class Buffer
|
Chris@16
|
177 >
|
Chris@16
|
178 class writable_postfix_increment_proxy<
|
Chris@16
|
179 range_detail::any_iterator<
|
Chris@16
|
180 Value
|
Chris@16
|
181 , Traversal
|
Chris@16
|
182 , Reference
|
Chris@16
|
183 , Difference
|
Chris@16
|
184 , Buffer
|
Chris@16
|
185 >
|
Chris@16
|
186 >
|
Chris@16
|
187 {
|
Chris@16
|
188 typedef range_detail::any_iterator<
|
Chris@16
|
189 Value
|
Chris@16
|
190 , Traversal
|
Chris@16
|
191 , Reference
|
Chris@16
|
192 , Difference
|
Chris@16
|
193 , Buffer
|
Chris@16
|
194 > any_iterator_type;
|
Chris@16
|
195 public:
|
Chris@16
|
196 typedef Value value_type;
|
Chris@16
|
197 typedef typename std::iterator_traits<any_iterator_type>::iterator_category iterator_category;
|
Chris@16
|
198 typedef Difference difference_type;
|
Chris@16
|
199 typedef typename iterator_pointer<any_iterator_type>::type pointer;
|
Chris@16
|
200 typedef Reference reference;
|
Chris@16
|
201
|
Chris@16
|
202 explicit writable_postfix_increment_proxy(any_iterator_type const& x)
|
Chris@16
|
203 : stored_value(*x)
|
Chris@16
|
204 , stored_iterator(x)
|
Chris@16
|
205 {}
|
Chris@16
|
206
|
Chris@16
|
207 // Dereferencing must return a proxy so that both *r++ = o and
|
Chris@16
|
208 // value_type(*r++) can work. In this case, *r is the same as
|
Chris@16
|
209 // *r++, and the conversion operator below is used to ensure
|
Chris@16
|
210 // readability.
|
Chris@16
|
211 writable_postfix_increment_proxy const&
|
Chris@16
|
212 operator*() const
|
Chris@16
|
213 {
|
Chris@16
|
214 return *this;
|
Chris@16
|
215 }
|
Chris@16
|
216
|
Chris@16
|
217 // Provides readability of *r++
|
Chris@16
|
218 operator value_type&() const
|
Chris@16
|
219 {
|
Chris@16
|
220 return stored_value;
|
Chris@16
|
221 }
|
Chris@16
|
222
|
Chris@16
|
223 // Provides writability of *r++
|
Chris@16
|
224 template <class T>
|
Chris@16
|
225 T const& operator=(T const& x) const
|
Chris@16
|
226 {
|
Chris@16
|
227 *this->stored_iterator = x;
|
Chris@16
|
228 return x;
|
Chris@16
|
229 }
|
Chris@16
|
230
|
Chris@16
|
231 // This overload just in case only non-const objects are writable
|
Chris@16
|
232 template <class T>
|
Chris@16
|
233 T& operator=(T& x) const
|
Chris@16
|
234 {
|
Chris@16
|
235 *this->stored_iterator = x;
|
Chris@16
|
236 return x;
|
Chris@16
|
237 }
|
Chris@16
|
238
|
Chris@16
|
239 // Provides X(r++)
|
Chris@16
|
240 operator any_iterator_type const&() const
|
Chris@16
|
241 {
|
Chris@16
|
242 return stored_iterator;
|
Chris@16
|
243 }
|
Chris@16
|
244
|
Chris@16
|
245 private:
|
Chris@16
|
246 mutable value_type stored_value;
|
Chris@16
|
247 any_iterator_type stored_iterator;
|
Chris@16
|
248 };
|
Chris@16
|
249
|
Chris@101
|
250 } //namespace detail
|
Chris@101
|
251 } //namespace iterators
|
Chris@16
|
252
|
Chris@16
|
253 namespace range_detail
|
Chris@16
|
254 {
|
Chris@16
|
255 template<
|
Chris@16
|
256 class Value
|
Chris@16
|
257 , class Traversal
|
Chris@16
|
258 , class Reference
|
Chris@16
|
259 , class Difference
|
Chris@16
|
260 , class Buffer
|
Chris@16
|
261 >
|
Chris@16
|
262 class any_iterator
|
Chris@16
|
263 : public iterator_facade<
|
Chris@16
|
264 any_iterator<
|
Chris@16
|
265 Value
|
Chris@16
|
266 , Traversal
|
Chris@16
|
267 , Reference
|
Chris@16
|
268 , Difference
|
Chris@16
|
269 , Buffer
|
Chris@16
|
270 >
|
Chris@16
|
271 , Value
|
Chris@16
|
272 , Traversal
|
Chris@16
|
273 , Reference
|
Chris@16
|
274 , Difference
|
Chris@16
|
275 >
|
Chris@16
|
276 {
|
Chris@16
|
277 template<
|
Chris@16
|
278 class OtherValue
|
Chris@16
|
279 , class OtherTraversal
|
Chris@16
|
280 , class OtherReference
|
Chris@16
|
281 , class OtherDifference
|
Chris@16
|
282 , class OtherBuffer
|
Chris@16
|
283 >
|
Chris@16
|
284 friend class any_iterator;
|
Chris@16
|
285
|
Chris@16
|
286 struct enabler {};
|
Chris@16
|
287 struct disabler {};
|
Chris@16
|
288
|
Chris@16
|
289 typedef typename any_iterator_interface_type_generator<
|
Chris@16
|
290 Traversal
|
Chris@16
|
291 , Reference
|
Chris@16
|
292 , Difference
|
Chris@16
|
293 , Buffer
|
Chris@16
|
294 >::type abstract_base_type;
|
Chris@16
|
295
|
Chris@16
|
296 typedef iterator_facade<
|
Chris@16
|
297 any_iterator<
|
Chris@16
|
298 Value
|
Chris@16
|
299 , Traversal
|
Chris@16
|
300 , Reference
|
Chris@16
|
301 , Difference
|
Chris@16
|
302 , Buffer
|
Chris@16
|
303 >
|
Chris@16
|
304 , Value
|
Chris@16
|
305 , Traversal
|
Chris@16
|
306 , Reference
|
Chris@16
|
307 , Difference
|
Chris@16
|
308 > base_type;
|
Chris@16
|
309
|
Chris@16
|
310 typedef Buffer buffer_type;
|
Chris@16
|
311
|
Chris@16
|
312 public:
|
Chris@16
|
313 typedef typename base_type::value_type value_type;
|
Chris@16
|
314 typedef typename base_type::reference reference;
|
Chris@16
|
315 typedef typename base_type::difference_type difference_type;
|
Chris@16
|
316
|
Chris@16
|
317 // Default constructor
|
Chris@16
|
318 any_iterator()
|
Chris@16
|
319 : m_impl(0) {}
|
Chris@16
|
320
|
Chris@16
|
321 // Simple copy construction without conversion
|
Chris@16
|
322 any_iterator(const any_iterator& other)
|
Chris@16
|
323 : base_type(other)
|
Chris@16
|
324 , m_impl(other.m_impl
|
Chris@16
|
325 ? other.m_impl->clone(m_buffer)
|
Chris@16
|
326 : 0)
|
Chris@16
|
327 {
|
Chris@16
|
328 }
|
Chris@16
|
329
|
Chris@16
|
330 // Simple assignment operator without conversion
|
Chris@16
|
331 any_iterator& operator=(const any_iterator& other)
|
Chris@16
|
332 {
|
Chris@16
|
333 if (this != &other)
|
Chris@16
|
334 {
|
Chris@16
|
335 if (m_impl)
|
Chris@16
|
336 m_impl->~abstract_base_type();
|
Chris@16
|
337 m_buffer.deallocate();
|
Chris@16
|
338 m_impl = 0;
|
Chris@16
|
339 if (other.m_impl)
|
Chris@16
|
340 m_impl = other.m_impl->clone(m_buffer);
|
Chris@16
|
341 }
|
Chris@16
|
342 return *this;
|
Chris@16
|
343 }
|
Chris@16
|
344
|
Chris@16
|
345 // Implicit conversion from another any_iterator where the
|
Chris@16
|
346 // conversion is from a non-const reference to a const reference
|
Chris@16
|
347 template<
|
Chris@16
|
348 class OtherValue
|
Chris@16
|
349 , class OtherTraversal
|
Chris@16
|
350 , class OtherReference
|
Chris@16
|
351 , class OtherDifference
|
Chris@16
|
352 >
|
Chris@16
|
353 any_iterator(const any_iterator<
|
Chris@16
|
354 OtherValue,
|
Chris@16
|
355 OtherTraversal,
|
Chris@16
|
356 OtherReference,
|
Chris@16
|
357 OtherDifference,
|
Chris@16
|
358 Buffer
|
Chris@16
|
359 >& other,
|
Chris@101
|
360 typename ::boost::enable_if<
|
Chris@16
|
361 typename mpl::and_<
|
Chris@16
|
362 typename is_mutable_reference<OtherReference>::type,
|
Chris@16
|
363 typename is_const_reference<Reference>::type
|
Chris@16
|
364 >::type,
|
Chris@16
|
365 enabler
|
Chris@16
|
366 >::type* = 0
|
Chris@16
|
367 )
|
Chris@16
|
368 : m_impl(other.m_impl
|
Chris@16
|
369 ? other.m_impl->clone_const_ref(m_buffer)
|
Chris@16
|
370 : 0
|
Chris@16
|
371 )
|
Chris@16
|
372 {
|
Chris@16
|
373 }
|
Chris@16
|
374
|
Chris@16
|
375 // Implicit conversion from another any_iterator where the
|
Chris@16
|
376 // reference types of the source and the target are references
|
Chris@16
|
377 // that are either both const, or both non-const.
|
Chris@16
|
378 template<
|
Chris@16
|
379 class OtherValue
|
Chris@16
|
380 , class OtherTraversal
|
Chris@16
|
381 , class OtherReference
|
Chris@16
|
382 , class OtherDifference
|
Chris@16
|
383 >
|
Chris@16
|
384 any_iterator(const any_iterator<
|
Chris@16
|
385 OtherValue
|
Chris@16
|
386 , OtherTraversal
|
Chris@16
|
387 , OtherReference
|
Chris@16
|
388 , OtherDifference
|
Chris@16
|
389 , Buffer
|
Chris@16
|
390 >& other,
|
Chris@101
|
391 typename ::boost::enable_if<
|
Chris@16
|
392 typename mpl::or_<
|
Chris@16
|
393 typename mpl::and_<
|
Chris@16
|
394 typename is_mutable_reference<OtherReference>::type,
|
Chris@16
|
395 typename is_mutable_reference<Reference>::type
|
Chris@16
|
396 >::type,
|
Chris@16
|
397 typename mpl::and_<
|
Chris@16
|
398 typename is_const_reference<OtherReference>::type,
|
Chris@16
|
399 typename is_const_reference<Reference>::type
|
Chris@16
|
400 >::type
|
Chris@16
|
401 >::type,
|
Chris@16
|
402 enabler
|
Chris@16
|
403 >::type* = 0
|
Chris@16
|
404 )
|
Chris@16
|
405 : m_impl(other.m_impl
|
Chris@16
|
406 ? other.m_impl->clone(m_buffer)
|
Chris@16
|
407 : 0
|
Chris@16
|
408 )
|
Chris@16
|
409 {
|
Chris@16
|
410 }
|
Chris@16
|
411
|
Chris@16
|
412 // Implicit conversion to an any_iterator that uses a value for
|
Chris@16
|
413 // the reference type.
|
Chris@16
|
414 template<
|
Chris@16
|
415 class OtherValue
|
Chris@16
|
416 , class OtherTraversal
|
Chris@16
|
417 , class OtherReference
|
Chris@16
|
418 , class OtherDifference
|
Chris@16
|
419 >
|
Chris@16
|
420 any_iterator(const any_iterator<
|
Chris@16
|
421 OtherValue
|
Chris@16
|
422 , OtherTraversal
|
Chris@16
|
423 , OtherReference
|
Chris@16
|
424 , OtherDifference
|
Chris@16
|
425 , Buffer
|
Chris@16
|
426 >& other,
|
Chris@101
|
427 typename ::boost::enable_if<
|
Chris@16
|
428 typename is_convertible_to_value_as_reference<
|
Chris@16
|
429 OtherReference
|
Chris@16
|
430 , Reference
|
Chris@16
|
431 >::type,
|
Chris@16
|
432 enabler
|
Chris@16
|
433 >::type* = 0
|
Chris@16
|
434 )
|
Chris@16
|
435 : m_impl(other.m_impl
|
Chris@16
|
436 ? other.m_impl->clone_reference_as_value(m_buffer)
|
Chris@16
|
437 : 0
|
Chris@16
|
438 )
|
Chris@16
|
439 {
|
Chris@16
|
440 }
|
Chris@16
|
441
|
Chris@16
|
442 any_iterator clone() const
|
Chris@16
|
443 {
|
Chris@16
|
444 any_iterator result;
|
Chris@16
|
445 if (m_impl)
|
Chris@16
|
446 result.m_impl = m_impl->clone(result.m_buffer);
|
Chris@16
|
447 return result;
|
Chris@16
|
448 }
|
Chris@16
|
449
|
Chris@16
|
450 any_iterator<
|
Chris@16
|
451 Value
|
Chris@16
|
452 , Traversal
|
Chris@16
|
453 , typename abstract_base_type::const_reference
|
Chris@16
|
454 , Difference
|
Chris@16
|
455 , Buffer
|
Chris@16
|
456 >
|
Chris@16
|
457 clone_const_ref() const
|
Chris@16
|
458 {
|
Chris@16
|
459 typedef any_iterator<
|
Chris@16
|
460 Value
|
Chris@16
|
461 , Traversal
|
Chris@16
|
462 , typename abstract_base_type::const_reference
|
Chris@16
|
463 , Difference
|
Chris@16
|
464 , Buffer
|
Chris@16
|
465 > result_type;
|
Chris@16
|
466
|
Chris@16
|
467 result_type result;
|
Chris@16
|
468
|
Chris@16
|
469 if (m_impl)
|
Chris@16
|
470 result.m_impl = m_impl->clone_const_ref(result.m_buffer);
|
Chris@16
|
471
|
Chris@16
|
472 return result;
|
Chris@16
|
473 }
|
Chris@16
|
474
|
Chris@16
|
475 // implicit conversion and construction from type-erasure-compatible
|
Chris@16
|
476 // iterators
|
Chris@16
|
477 template<class WrappedIterator>
|
Chris@16
|
478 explicit any_iterator(
|
Chris@16
|
479 const WrappedIterator& wrapped_iterator,
|
Chris@16
|
480 typename disable_if<
|
Chris@16
|
481 typename is_any_iterator<WrappedIterator>::type
|
Chris@16
|
482 , disabler
|
Chris@16
|
483 >::type* = 0
|
Chris@16
|
484 )
|
Chris@16
|
485 {
|
Chris@16
|
486 typedef typename any_iterator_wrapper_type_generator<
|
Chris@16
|
487 WrappedIterator
|
Chris@16
|
488 , Traversal
|
Chris@16
|
489 , Reference
|
Chris@16
|
490 , Difference
|
Chris@16
|
491 , Buffer
|
Chris@16
|
492 >::type wrapper_type;
|
Chris@16
|
493
|
Chris@16
|
494 void* ptr = m_buffer.allocate(sizeof(wrapper_type));
|
Chris@16
|
495 m_impl = new(ptr) wrapper_type(wrapped_iterator);
|
Chris@16
|
496 }
|
Chris@16
|
497
|
Chris@16
|
498 ~any_iterator()
|
Chris@16
|
499 {
|
Chris@16
|
500 // manually run the destructor, the deallocation is automatically
|
Chris@16
|
501 // handled by the any_iterator_small_buffer base class.
|
Chris@16
|
502 if (m_impl)
|
Chris@16
|
503 m_impl->~abstract_base_type();
|
Chris@16
|
504 }
|
Chris@16
|
505
|
Chris@16
|
506 private:
|
Chris@16
|
507 friend class ::boost::iterator_core_access;
|
Chris@16
|
508
|
Chris@16
|
509 Reference dereference() const
|
Chris@16
|
510 {
|
Chris@16
|
511 BOOST_ASSERT( m_impl );
|
Chris@16
|
512 return m_impl->dereference();
|
Chris@16
|
513 }
|
Chris@16
|
514
|
Chris@16
|
515 bool equal(const any_iterator& other) const
|
Chris@16
|
516 {
|
Chris@16
|
517 return (m_impl == other.m_impl)
|
Chris@16
|
518 || (m_impl && other.m_impl && m_impl->equal(*other.m_impl));
|
Chris@16
|
519 }
|
Chris@16
|
520
|
Chris@16
|
521 void increment()
|
Chris@16
|
522 {
|
Chris@16
|
523 BOOST_ASSERT( m_impl );
|
Chris@16
|
524 m_impl->increment();
|
Chris@16
|
525 }
|
Chris@16
|
526
|
Chris@16
|
527 void decrement()
|
Chris@16
|
528 {
|
Chris@16
|
529 BOOST_ASSERT( m_impl );
|
Chris@16
|
530 m_impl->decrement();
|
Chris@16
|
531 }
|
Chris@16
|
532
|
Chris@16
|
533 Difference distance_to(const any_iterator& other) const
|
Chris@16
|
534 {
|
Chris@16
|
535 return m_impl && other.m_impl
|
Chris@16
|
536 ? m_impl->distance_to(*other.m_impl)
|
Chris@16
|
537 : 0;
|
Chris@16
|
538 }
|
Chris@16
|
539
|
Chris@16
|
540 void advance(Difference offset)
|
Chris@16
|
541 {
|
Chris@16
|
542 BOOST_ASSERT( m_impl );
|
Chris@16
|
543 m_impl->advance(offset);
|
Chris@16
|
544 }
|
Chris@16
|
545
|
Chris@16
|
546 any_iterator& swap(any_iterator& other)
|
Chris@16
|
547 {
|
Chris@16
|
548 BOOST_ASSERT( this != &other );
|
Chris@16
|
549 // grab a temporary copy of the other iterator
|
Chris@16
|
550 any_iterator tmp(other);
|
Chris@16
|
551
|
Chris@16
|
552 // deallocate the other iterator, taking care to obey the
|
Chris@16
|
553 // class-invariants in-case of exceptions later
|
Chris@16
|
554 if (other.m_impl)
|
Chris@16
|
555 {
|
Chris@16
|
556 other.m_impl->~abstract_base_type();
|
Chris@16
|
557 other.m_buffer.deallocate();
|
Chris@16
|
558 other.m_impl = 0;
|
Chris@16
|
559 }
|
Chris@16
|
560
|
Chris@16
|
561 // If this is a non-null iterator then we need to put
|
Chris@16
|
562 // a clone of this iterators implementation into the other
|
Chris@16
|
563 // iterator.
|
Chris@16
|
564 // We can't just swap because of the small buffer optimization.
|
Chris@16
|
565 if (m_impl)
|
Chris@16
|
566 {
|
Chris@16
|
567 other.m_impl = m_impl->clone(other.m_buffer);
|
Chris@16
|
568 m_impl->~abstract_base_type();
|
Chris@16
|
569 m_buffer.deallocate();
|
Chris@16
|
570 m_impl = 0;
|
Chris@16
|
571 }
|
Chris@16
|
572
|
Chris@16
|
573 // assign to this instance a clone of the temporarily held
|
Chris@16
|
574 // tmp which represents the input other parameter at the
|
Chris@16
|
575 // start of execution of this function.
|
Chris@16
|
576 if (tmp.m_impl)
|
Chris@16
|
577 m_impl = tmp.m_impl->clone(m_buffer);
|
Chris@16
|
578
|
Chris@16
|
579 return *this;
|
Chris@16
|
580 }
|
Chris@16
|
581
|
Chris@16
|
582 buffer_type m_buffer;
|
Chris@16
|
583 abstract_base_type* m_impl;
|
Chris@16
|
584 };
|
Chris@16
|
585
|
Chris@16
|
586 } // namespace range_detail
|
Chris@16
|
587 } // namespace boost
|
Chris@16
|
588
|
Chris@16
|
589 #endif // include guard
|