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