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