Line data Source code
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/core/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 :
43 : namespace boost {
44 : namespace 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 0 : static result_type apply(T& x)
345 : {
346 0 : 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 14240 : static typename Facade::reference dereference(Facade const& f)
549 : {
550 0 : return f.dereference();
551 : }
552 :
553 : template <class Facade>
554 14240 : static void increment(Facade& f)
555 : {
556 0 : 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 16376 : static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_)
567 : {
568 16376 : 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 0 : static typename Facade1::difference_type distance_from(
585 : Facade1 const& f1, Facade2 const& f2, mpl::true_)
586 : {
587 0 : 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 14240 : reference operator*() const
655 : {
656 14240 : return iterator_core_access::dereference(this->derived());
657 : }
658 :
659 0 : pointer operator->() const
660 : {
661 0 : return operator_arrow_dispatch_::apply(*this->derived());
662 : }
663 :
664 14240 : Derived& operator++()
665 : {
666 14240 : iterator_core_access::increment(this->derived());
667 14240 : return this->derived();
668 : }
669 :
670 : protected:
671 : //
672 : // Curiously Recurring Template interface.
673 : //
674 14240 : Derived& derived()
675 : {
676 : return *static_cast<Derived*>(this);
677 : }
678 :
679 14240 : 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 0 : 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 0 : tmp(*static_cast<I*>(&i));
798 :
799 0 : ++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 0 : BOOST_ITERATOR_FACADE_RELATION(==, return, equal)
901 16376 : 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 0 : 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 :
974 : using iterators::iterator_core_access;
975 : using iterators::iterator_facade;
976 :
977 : } // namespace boost
978 :
979 : #include <boost/iterator/detail/config_undef.hpp>
980 :
981 : #endif // BOOST_ITERATOR_FACADE_23022003THW_HPP
|