1// (C) Copyright David Abrahams 2002.
2// (C) Copyright Jeremy Siek 2002.
3// (C) Copyright Thomas Witt 2002.
4// Distributed under the Boost Software License, Version 1.0. (See
5// accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7#ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP
8#define BOOST_ITERATOR_FACADE_23022003THW_HPP
9
10#include <boost/config.hpp>
11#include <boost/iterator.hpp>
12#include <boost/iterator/interoperable.hpp>
13#include <boost/iterator/iterator_traits.hpp>
14#include <boost/iterator/iterator_categories.hpp>
15
16#include <boost/iterator/detail/facade_iterator_category.hpp>
17#include <boost/iterator/detail/enable_if.hpp>
18
19#include <boost/static_assert.hpp>
20#include <boost/utility/addressof.hpp>
21
22#include <boost/type_traits/is_same.hpp>
23#include <boost/type_traits/add_const.hpp>
24#include <boost/type_traits/add_pointer.hpp>
25#include <boost/type_traits/add_lvalue_reference.hpp>
26#include <boost/type_traits/remove_const.hpp>
27#include <boost/type_traits/remove_reference.hpp>
28#include <boost/type_traits/is_convertible.hpp>
29#include <boost/type_traits/is_pod.hpp>
30
31#include <boost/mpl/eval_if.hpp>
32#include <boost/mpl/if.hpp>
33#include <boost/mpl/or.hpp>
34#include <boost/mpl/and.hpp>
35#include <boost/mpl/not.hpp>
36#include <boost/mpl/always.hpp>
37#include <boost/mpl/apply.hpp>
38#include <boost/mpl/identity.hpp>
39
40#include <boost/iterator/detail/config_def.hpp> // this goes last
41
42namespace boost {
43namespace iterators {
44
45 // This forward declaration is required for the friend declaration
46 // in iterator_core_access
47 template <class I, class V, class TC, class R, class D> class iterator_facade;
48
49 namespace detail
50 {
51 // A binary metafunction class that always returns bool. VC6
52 // ICEs on mpl::always<bool>, probably because of the default
53 // parameters.
54 struct always_bool2
55 {
56 template <class T, class U>
57 struct apply
58 {
59 typedef bool type;
60 };
61 };
62
63 // The type trait checks if the category or traversal is at least as advanced as the specified required traversal
64 template< typename CategoryOrTraversal, typename Required >
65 struct is_traversal_at_least :
66 public boost::is_convertible< typename iterator_category_to_traversal< CategoryOrTraversal >::type, Required >
67 {};
68
69 //
70 // enable if for use in operator implementation.
71 //
72 template <
73 class Facade1
74 , class Facade2
75 , class Return
76 >
77 struct enable_if_interoperable :
78 public boost::iterators::enable_if<
79 is_interoperable< Facade1, Facade2 >
80 , Return
81 >
82 {};
83
84 //
85 // enable if for use in implementation of operators specific for random access traversal.
86 //
87 template <
88 class Facade1
89 , class Facade2
90 , class Return
91 >
92 struct enable_if_interoperable_and_random_access_traversal :
93 public boost::iterators::enable_if<
94 mpl::and_<
95 is_interoperable< Facade1, Facade2 >
96 , is_traversal_at_least< typename iterator_category< Facade1 >::type, random_access_traversal_tag >
97 , is_traversal_at_least< typename iterator_category< Facade2 >::type, random_access_traversal_tag >
98 >
99 , Return
100 >
101 {};
102
103 //
104 // Generates associated types for an iterator_facade with the
105 // given parameters.
106 //
107 template <
108 class ValueParam
109 , class CategoryOrTraversal
110 , class Reference
111 , class Difference
112 >
113 struct iterator_facade_types
114 {
115 typedef typename facade_iterator_category<
116 CategoryOrTraversal, ValueParam, Reference
117 >::type iterator_category;
118
119 typedef typename remove_const<ValueParam>::type value_type;
120
121 // Not the real associated pointer type
122 typedef typename mpl::eval_if<
123 boost::iterators::detail::iterator_writability_disabled<ValueParam,Reference>
124 , add_pointer<const value_type>
125 , add_pointer<value_type>
126 >::type pointer;
127
128# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
129 && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
130 || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
131 || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \
132 || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310)
133
134 // To interoperate with some broken library/compiler
135 // combinations, user-defined iterators must be derived from
136 // std::iterator. It is possible to implement a standard
137 // library for broken compilers without this limitation.
138# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
139
140 typedef
141 iterator<iterator_category, value_type, Difference, pointer, Reference>
142 base;
143# endif
144 };
145
146 // iterators whose dereference operators reference the same value
147 // for all iterators into the same sequence (like many input
148 // iterators) need help with their postfix ++: the referenced
149 // value must be read and stored away before the increment occurs
150 // so that *a++ yields the originally referenced element and not
151 // the next one.
152 template <class Iterator>
153 class postfix_increment_proxy
154 {
155 typedef typename iterator_value<Iterator>::type value_type;
156 public:
157 explicit postfix_increment_proxy(Iterator const& x)
158 : stored_value(*x)
159 {}
160
161 // Returning a mutable reference allows nonsense like
162 // (*r++).mutate(), but it imposes fewer assumptions about the
163 // behavior of the value_type. In particular, recall that
164 // (*r).mutate() is legal if operator* returns by value.
165 value_type&
166 operator*() const
167 {
168 return this->stored_value;
169 }
170 private:
171 mutable value_type stored_value;
172 };
173
174 //
175 // In general, we can't determine that such an iterator isn't
176 // writable -- we also need to store a copy of the old iterator so
177 // that it can be written into.
178 template <class Iterator>
179 class writable_postfix_increment_proxy
180 {
181 typedef typename iterator_value<Iterator>::type value_type;
182 public:
183 explicit writable_postfix_increment_proxy(Iterator const& x)
184 : stored_value(*x)
185 , stored_iterator(x)
186 {}
187
188 // Dereferencing must return a proxy so that both *r++ = o and
189 // value_type(*r++) can work. In this case, *r is the same as
190 // *r++, and the conversion operator below is used to ensure
191 // readability.
192 writable_postfix_increment_proxy const&
193 operator*() const
194 {
195 return *this;
196 }
197
198 // Provides readability of *r++
199 operator value_type&() const
200 {
201 return stored_value;
202 }
203
204 // Provides writability of *r++
205 template <class T>
206 T const& operator=(T const& x) const
207 {
208 *this->stored_iterator = x;
209 return x;
210 }
211
212 // This overload just in case only non-const objects are writable
213 template <class T>
214 T& operator=(T& x) const
215 {
216 *this->stored_iterator = x;
217 return x;
218 }
219
220 // Provides X(r++)
221 operator Iterator const&() const
222 {
223 return stored_iterator;
224 }
225
226 private:
227 mutable value_type stored_value;
228 Iterator stored_iterator;
229 };
230
231# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
232
233 template <class Reference, class Value>
234 struct is_non_proxy_reference_impl
235 {
236 static Reference r;
237
238 template <class R>
239 static typename mpl::if_<
240 is_convertible<
241 R const volatile*
242 , Value const volatile*
243 >
244 , char[1]
245 , char[2]
246 >::type& helper(R const&);
247
248 BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1);
249 };
250
251 template <class Reference, class Value>
252 struct is_non_proxy_reference
253 : mpl::bool_<
254 is_non_proxy_reference_impl<Reference, Value>::value
255 >
256 {};
257# else
258 template <class Reference, class Value>
259 struct is_non_proxy_reference
260 : is_convertible<
261 typename remove_reference<Reference>::type
262 const volatile*
263 , Value const volatile*
264 >
265 {};
266# endif
267
268 // A metafunction to choose the result type of postfix ++
269 //
270 // Because the C++98 input iterator requirements say that *r++ has
271 // type T (value_type), implementations of some standard
272 // algorithms like lexicographical_compare may use constructions
273 // like:
274 //
275 // *r++ < *s++
276 //
277 // If *r++ returns a proxy (as required if r is writable but not
278 // multipass), this sort of expression will fail unless the proxy
279 // supports the operator<. Since there are any number of such
280 // operations, we're not going to try to support them. Therefore,
281 // even if r++ returns a proxy, *r++ will only return a proxy if
282 // *r also returns a proxy.
283 template <class Iterator, class Value, class Reference, class CategoryOrTraversal>
284 struct postfix_increment_result
285 : mpl::eval_if<
286 mpl::and_<
287 // A proxy is only needed for readable iterators
288 is_convertible<
289 Reference
290 // Use add_lvalue_reference to form `reference to Value` due to
291 // some (strict) C++03 compilers (e.g. `gcc -std=c++03`) reject
292 // 'reference-to-reference' in the template which described in CWG
293 // DR106.
294 // http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_defects.html#106
295 , typename add_lvalue_reference<Value const>::type
296 >
297
298 // No multipass iterator can have values that disappear
299 // before positions can be re-visited
300 , mpl::not_<
301 is_convertible<
302 typename iterator_category_to_traversal<CategoryOrTraversal>::type
303 , forward_traversal_tag
304 >
305 >
306 >
307 , mpl::if_<
308 is_non_proxy_reference<Reference,Value>
309 , postfix_increment_proxy<Iterator>
310 , writable_postfix_increment_proxy<Iterator>
311 >
312 , mpl::identity<Iterator>
313 >
314 {};
315
316 // operator->() needs special support for input iterators to strictly meet the
317 // standard's requirements. If *i is not a reference type, we must still
318 // produce an lvalue to which a pointer can be formed. We do that by
319 // returning a proxy object containing an instance of the reference object.
320 template <class Reference, class Pointer>
321 struct operator_arrow_dispatch // proxy references
322 {
323 struct proxy
324 {
325 explicit proxy(Reference const & x) : m_ref(x) {}
326 Reference* operator->() { return boost::addressof(m_ref); }
327 // This function is needed for MWCW and BCC, which won't call
328 // operator-> again automatically per 13.3.1.2 para 8
329 operator Reference*() { return boost::addressof(m_ref); }
330 Reference m_ref;
331 };
332 typedef proxy result_type;
333 static result_type apply(Reference const & x)
334 {
335 return result_type(x);
336 }
337 };
338
339 template <class T, class Pointer>
340 struct operator_arrow_dispatch<T&, Pointer> // "real" references
341 {
342 typedef Pointer result_type;
343 static result_type apply(T& x)
344 {
345 return boost::addressof(x);
346 }
347 };
348
349 // A proxy return type for operator[], needed to deal with
350 // iterators that may invalidate referents upon destruction.
351 // Consider the temporary iterator in *(a + n)
352 template <class Iterator>
353 class operator_brackets_proxy
354 {
355 // Iterator is actually an iterator_facade, so we do not have to
356 // go through iterator_traits to access the traits.
357 typedef typename Iterator::reference reference;
358 typedef typename Iterator::value_type value_type;
359
360 public:
361 operator_brackets_proxy(Iterator const& iter)
362 : m_iter(iter)
363 {}
364
365 operator reference() const
366 {
367 return *m_iter;
368 }
369
370 operator_brackets_proxy& operator=(value_type const& val)
371 {
372 *m_iter = val;
373 return *this;
374 }
375
376 private:
377 Iterator m_iter;
378 };
379
380 // A metafunction that determines whether operator[] must return a
381 // proxy, or whether it can simply return a copy of the value_type.
382 template <class ValueType, class Reference>
383 struct use_operator_brackets_proxy
384 : mpl::not_<
385 mpl::and_<
386 // Really we want an is_copy_constructible trait here,
387 // but is_POD will have to suffice in the meantime.
388 boost::is_POD<ValueType>
389 , iterator_writability_disabled<ValueType,Reference>
390 >
391 >
392 {};
393
394 template <class Iterator, class Value, class Reference>
395 struct operator_brackets_result
396 {
397 typedef typename mpl::if_<
398 use_operator_brackets_proxy<Value,Reference>
399 , operator_brackets_proxy<Iterator>
400 , Value
401 >::type type;
402 };
403
404 template <class Iterator>
405 operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_)
406 {
407 return operator_brackets_proxy<Iterator>(iter);
408 }
409
410 template <class Iterator>
411 typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_)
412 {
413 return *iter;
414 }
415
416 struct choose_difference_type
417 {
418 template <class I1, class I2>
419 struct apply
420 :
421# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
422 iterator_difference<I1>
423# else
424 mpl::eval_if<
425 is_convertible<I2,I1>
426 , iterator_difference<I1>
427 , iterator_difference<I2>
428 >
429# endif
430 {};
431
432 };
433
434 template <
435 class Derived
436 , class Value
437 , class CategoryOrTraversal
438 , class Reference
439 , class Difference
440 , bool IsBidirectionalTraversal
441 , bool IsRandomAccessTraversal
442 >
443 class iterator_facade_base;
444
445 } // namespace detail
446
447
448 // Macros which describe the declarations of binary operators
449# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
450# define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \
451 template < \
452 class Derived1, class V1, class TC1, class Reference1, class Difference1 \
453 , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
454 > \
455 prefix typename mpl::apply2<result_type,Derived1,Derived2>::type \
456 operator op( \
457 iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
458 , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
459# else
460# define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \
461 template < \
462 class Derived1, class V1, class TC1, class Reference1, class Difference1 \
463 , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
464 > \
465 prefix typename enabler< \
466 Derived1, Derived2 \
467 , typename mpl::apply2<result_type,Derived1,Derived2>::type \
468 >::type \
469 operator op( \
470 iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
471 , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
472# endif
473
474# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
475 BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable)
476
477# define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(prefix, op, result_type) \
478 BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable_and_random_access_traversal)
479
480# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
481 template <class Derived, class V, class TC, class R, class D> \
482 prefix typename boost::iterators::enable_if< \
483 boost::iterators::detail::is_traversal_at_least< TC, boost::iterators::random_access_traversal_tag >, \
484 Derived \
485 >::type operator+ args
486
487 //
488 // Helper class for granting access to the iterator core interface.
489 //
490 // The simple core interface is used by iterator_facade. The core
491 // interface of a user/library defined iterator type should not be made public
492 // so that it does not clutter the public interface. Instead iterator_core_access
493 // should be made friend so that iterator_facade can access the core
494 // interface through iterator_core_access.
495 //
496 class iterator_core_access
497 {
498# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
499 // Tasteless as this may seem, making all members public allows member templates
500 // to work in the absence of member template friends.
501 public:
502# else
503
504 template <class I, class V, class TC, class R, class D> friend class iterator_facade;
505 template <class I, class V, class TC, class R, class D, bool IsBidirectionalTraversal, bool IsRandomAccessTraversal>
506 friend class detail::iterator_facade_base;
507
508# define BOOST_ITERATOR_FACADE_RELATION(op) \
509 BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::iterators::detail::always_bool2);
510
511 BOOST_ITERATOR_FACADE_RELATION(==)
512 BOOST_ITERATOR_FACADE_RELATION(!=)
513
514# undef BOOST_ITERATOR_FACADE_RELATION
515
516# define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op) \
517 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(friend,op, boost::iterators::detail::always_bool2);
518
519 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<)
520 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>)
521 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=)
522 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=)
523
524# undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION
525
526 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(
527 friend, -, boost::iterators::detail::choose_difference_type)
528 ;
529
530 BOOST_ITERATOR_FACADE_PLUS_HEAD(
531 friend inline
532 , (iterator_facade<Derived, V, TC, R, D> const&
533 , typename Derived::difference_type)
534 )
535 ;
536
537 BOOST_ITERATOR_FACADE_PLUS_HEAD(
538 friend inline
539 , (typename Derived::difference_type
540 , iterator_facade<Derived, V, TC, R, D> const&)
541 )
542 ;
543
544# endif
545
546 template <class Facade>
547 static typename Facade::reference dereference(Facade const& f)
548 {
549 return f.dereference();
550 }
551
552 template <class Facade>
553 static void increment(Facade& f)
554 {
555 f.increment();
556 }
557
558 template <class Facade>
559 static void decrement(Facade& f)
560 {
561 f.decrement();
562 }
563
564 template <class Facade1, class Facade2>
565 static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_)
566 {
567 return f1.equal(f2);
568 }
569
570 template <class Facade1, class Facade2>
571 static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_)
572 {
573 return f2.equal(f1);
574 }
575
576 template <class Facade>
577 static void advance(Facade& f, typename Facade::difference_type n)
578 {
579 f.advance(n);
580 }
581
582 template <class Facade1, class Facade2>
583 static typename Facade1::difference_type distance_from(
584 Facade1 const& f1, Facade2 const& f2, mpl::true_)
585 {
586 return -f1.distance_to(f2);
587 }
588
589 template <class Facade1, class Facade2>
590 static typename Facade2::difference_type distance_from(
591 Facade1 const& f1, Facade2 const& f2, mpl::false_)
592 {
593 return f2.distance_to(f1);
594 }
595
596 //
597 // Curiously Recurring Template interface.
598 //
599 template <class I, class V, class TC, class R, class D>
600 static I& derived(iterator_facade<I,V,TC,R,D>& facade)
601 {
602 return *static_cast<I*>(&facade);
603 }
604
605 template <class I, class V, class TC, class R, class D>
606 static I const& derived(iterator_facade<I,V,TC,R,D> const& facade)
607 {
608 return *static_cast<I const*>(&facade);
609 }
610
611 // objects of this class are useless
612 BOOST_DELETED_FUNCTION(iterator_core_access())
613 };
614
615 namespace detail {
616
617 // Implementation for forward traversal iterators
618 template <
619 class Derived
620 , class Value
621 , class CategoryOrTraversal
622 , class Reference
623 , class Difference
624 >
625 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false >
626# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
627 : public boost::iterators::detail::iterator_facade_types<
628 Value, CategoryOrTraversal, Reference, Difference
629 >::base
630# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
631# endif
632 {
633 private:
634 typedef boost::iterators::detail::iterator_facade_types<
635 Value, CategoryOrTraversal, Reference, Difference
636 > associated_types;
637
638 typedef boost::iterators::detail::operator_arrow_dispatch<
639 Reference
640 , typename associated_types::pointer
641 > operator_arrow_dispatch_;
642
643 public:
644 typedef typename associated_types::value_type value_type;
645 typedef Reference reference;
646 typedef Difference difference_type;
647
648 typedef typename operator_arrow_dispatch_::result_type pointer;
649
650 typedef typename associated_types::iterator_category iterator_category;
651
652 public:
653 reference operator*() const
654 {
655 return iterator_core_access::dereference(this->derived());
656 }
657
658 pointer operator->() const
659 {
660 return operator_arrow_dispatch_::apply(*this->derived());
661 }
662
663 Derived& operator++()
664 {
665 iterator_core_access::increment(this->derived());
666 return this->derived();
667 }
668
669 protected:
670 //
671 // Curiously Recurring Template interface.
672 //
673 Derived& derived()
674 {
675 return *static_cast<Derived*>(this);
676 }
677
678 Derived const& derived() const
679 {
680 return *static_cast<Derived const*>(this);
681 }
682 };
683
684 // Implementation for bidirectional traversal iterators
685 template <
686 class Derived
687 , class Value
688 , class CategoryOrTraversal
689 , class Reference
690 , class Difference
691 >
692 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > :
693 public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false >
694 {
695 public:
696 Derived& operator--()
697 {
698 iterator_core_access::decrement(this->derived());
699 return this->derived();
700 }
701
702 Derived operator--(int)
703 {
704 Derived tmp(this->derived());
705 --*this;
706 return tmp;
707 }
708 };
709
710 // Implementation for random access traversal iterators
711 template <
712 class Derived
713 , class Value
714 , class CategoryOrTraversal
715 , class Reference
716 , class Difference
717 >
718 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, true > :
719 public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false >
720 {
721 private:
722 typedef iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > base_type;
723
724 public:
725 typedef typename base_type::reference reference;
726 typedef typename base_type::difference_type difference_type;
727
728 public:
729 typename boost::iterators::detail::operator_brackets_result<Derived, Value, reference>::type
730 operator[](difference_type n) const
731 {
732 typedef boost::iterators::detail::use_operator_brackets_proxy<Value, Reference> use_proxy;
733
734 return boost::iterators::detail::make_operator_brackets_result<Derived>(
735 this->derived() + n
736 , use_proxy()
737 );
738 }
739
740 Derived& operator+=(difference_type n)
741 {
742 iterator_core_access::advance(this->derived(), n);
743 return this->derived();
744 }
745
746 Derived& operator-=(difference_type n)
747 {
748 iterator_core_access::advance(this->derived(), -n);
749 return this->derived();
750 }
751
752 Derived operator-(difference_type x) const
753 {
754 Derived result(this->derived());
755 return result -= x;
756 }
757 };
758
759 } // namespace detail
760
761 //
762 // iterator_facade - use as a public base class for defining new
763 // standard-conforming iterators.
764 //
765 template <
766 class Derived // The derived iterator type being constructed
767 , class Value
768 , class CategoryOrTraversal
769 , class Reference = Value&
770 , class Difference = std::ptrdiff_t
771 >
772 class iterator_facade :
773 public detail::iterator_facade_base<
774 Derived,
775 Value,
776 CategoryOrTraversal,
777 Reference,
778 Difference,
779 detail::is_traversal_at_least< CategoryOrTraversal, bidirectional_traversal_tag >::value,
780 detail::is_traversal_at_least< CategoryOrTraversal, random_access_traversal_tag >::value
781 >
782 {
783 protected:
784 // For use by derived classes
785 typedef iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> iterator_facade_;
786 };
787
788 template <class I, class V, class TC, class R, class D>
789 inline typename boost::iterators::detail::postfix_increment_result<I,V,R,TC>::type
790 operator++(
791 iterator_facade<I,V,TC,R,D>& i
792 , int
793 )
794 {
795 typename boost::iterators::detail::postfix_increment_result<I,V,R,TC>::type
796 tmp(*static_cast<I*>(&i));
797
798 ++i;
799
800 return tmp;
801 }
802
803
804 //
805 // Comparison operator implementation. The library supplied operators
806 // enables the user to provide fully interoperable constant/mutable
807 // iterator types. I.e. the library provides all operators
808 // for all mutable/constant iterator combinations.
809 //
810 // Note though that this kind of interoperability for constant/mutable
811 // iterators is not required by the standard for container iterators.
812 // All the standard asks for is a conversion mutable -> constant.
813 // Most standard library implementations nowadays provide fully interoperable
814 // iterator implementations, but there are still heavily used implementations
815 // that do not provide them. (Actually it's even worse, they do not provide
816 // them for only a few iterators.)
817 //
818 // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should
819 // enable the user to turn off mixed type operators
820 //
821 // The library takes care to provide only the right operator overloads.
822 // I.e.
823 //
824 // bool operator==(Iterator, Iterator);
825 // bool operator==(ConstIterator, Iterator);
826 // bool operator==(Iterator, ConstIterator);
827 // bool operator==(ConstIterator, ConstIterator);
828 //
829 // ...
830 //
831 // In order to do so it uses c++ idioms that are not yet widely supported
832 // by current compiler releases. The library is designed to degrade gracefully
833 // in the face of compiler deficiencies. In general compiler
834 // deficiencies result in less strict error checking and more obscure
835 // error messages, functionality is not affected.
836 //
837 // For full operation compiler support for "Substitution Failure Is Not An Error"
838 // (aka. enable_if) and boost::is_convertible is required.
839 //
840 // The following problems occur if support is lacking.
841 //
842 // Pseudo code
843 //
844 // ---------------
845 // AdaptorA<Iterator1> a1;
846 // AdaptorA<Iterator2> a2;
847 //
848 // // This will result in a no such overload error in full operation
849 // // If enable_if or is_convertible is not supported
850 // // The instantiation will fail with an error hopefully indicating that
851 // // there is no operator== for Iterator1, Iterator2
852 // // The same will happen if no enable_if is used to remove
853 // // false overloads from the templated conversion constructor
854 // // of AdaptorA.
855 //
856 // a1 == a2;
857 // ----------------
858 //
859 // AdaptorA<Iterator> a;
860 // AdaptorB<Iterator> b;
861 //
862 // // This will result in a no such overload error in full operation
863 // // If enable_if is not supported the static assert used
864 // // in the operator implementation will fail.
865 // // This will accidently work if is_convertible is not supported.
866 //
867 // a == b;
868 // ----------------
869 //
870
871# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
872# define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_()
873# else
874# define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible<a,b>()
875# endif
876
877# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \
878 BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \
879 { \
880 /* For those compilers that do not support enable_if */ \
881 BOOST_STATIC_ASSERT(( \
882 is_interoperable< Derived1, Derived2 >::value \
883 )); \
884 return_prefix iterator_core_access::base_op( \
885 *static_cast<Derived1 const*>(&lhs) \
886 , *static_cast<Derived2 const*>(&rhs) \
887 , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
888 ); \
889 }
890
891# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
892 BOOST_ITERATOR_FACADE_INTEROP( \
893 op \
894 , boost::iterators::detail::always_bool2 \
895 , return_prefix \
896 , base_op \
897 )
898
899 BOOST_ITERATOR_FACADE_RELATION(==, return, equal)
900 BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal)
901
902# undef BOOST_ITERATOR_FACADE_RELATION
903
904
905# define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(op, result_type, return_prefix, base_op) \
906 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(inline, op, result_type) \
907 { \
908 /* For those compilers that do not support enable_if */ \
909 BOOST_STATIC_ASSERT(( \
910 is_interoperable< Derived1, Derived2 >::value && \
911 boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived1 >::type, random_access_traversal_tag >::value && \
912 boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived2 >::type, random_access_traversal_tag >::value \
913 )); \
914 return_prefix iterator_core_access::base_op( \
915 *static_cast<Derived1 const*>(&lhs) \
916 , *static_cast<Derived2 const*>(&rhs) \
917 , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
918 ); \
919 }
920
921# define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op, return_prefix, base_op) \
922 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( \
923 op \
924 , boost::iterators::detail::always_bool2 \
925 , return_prefix \
926 , base_op \
927 )
928
929 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<, return 0 >, distance_from)
930 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>, return 0 <, distance_from)
931 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=, return 0 >=, distance_from)
932 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=, return 0 <=, distance_from)
933
934# undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION
935
936 // operator- requires an additional part in the static assertion
937 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(
938 -
939 , boost::iterators::detail::choose_difference_type
940 , return
941 , distance_from
942 )
943
944# undef BOOST_ITERATOR_FACADE_INTEROP
945# undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS
946
947# define BOOST_ITERATOR_FACADE_PLUS(args) \
948 BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \
949 { \
950 Derived tmp(static_cast<Derived const&>(i)); \
951 return tmp += n; \
952 }
953
954 BOOST_ITERATOR_FACADE_PLUS((
955 iterator_facade<Derived, V, TC, R, D> const& i
956 , typename Derived::difference_type n
957 ))
958
959 BOOST_ITERATOR_FACADE_PLUS((
960 typename Derived::difference_type n
961 , iterator_facade<Derived, V, TC, R, D> const& i
962 ))
963
964# undef BOOST_ITERATOR_FACADE_PLUS
965# undef BOOST_ITERATOR_FACADE_PLUS_HEAD
966
967# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD
968# undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD
969# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL
970
971} // namespace iterators
972
973using iterators::iterator_core_access;
974using iterators::iterator_facade;
975
976} // namespace boost
977
978#include <boost/iterator/detail/config_undef.hpp>
979
980#endif // BOOST_ITERATOR_FACADE_23022003THW_HPP
981

source code of boost/boost/iterator/iterator_facade.hpp