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