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