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