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