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