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
10 #include <boost/iterator.hpp>
11 #include <boost/iterator/interoperable.hpp>
12 #include <boost/iterator/iterator_traits.hpp>
14 #include <boost/iterator/detail/facade_iterator_category.hpp>
15 #include <boost/iterator/detail/enable_if.hpp>
17 #include <boost/implicit_cast.hpp>
18 #include <boost/static_assert.hpp>
20 #include <boost/type_traits/is_same.hpp>
21 #include <boost/type_traits/add_const.hpp>
22 #include <boost/type_traits/add_pointer.hpp>
23 #include <boost/type_traits/remove_const.hpp>
24 #include <boost/type_traits/remove_reference.hpp>
25 #include <boost/type_traits/is_convertible.hpp>
26 #include <boost/type_traits/is_pod.hpp>
28 #include <boost/mpl/eval_if.hpp>
29 #include <boost/mpl/if.hpp>
30 #include <boost/mpl/or.hpp>
31 #include <boost/mpl/and.hpp>
32 #include <boost/mpl/not.hpp>
33 #include <boost/mpl/always.hpp>
34 #include <boost/mpl/apply.hpp>
35 #include <boost/mpl/identity.hpp>
37 #include <boost/iterator/detail/config_def.hpp> // this goes last
41 // This forward declaration is required for the friend declaration
42 // in iterator_core_access
43 template <class I
, class V
, class TC
, class R
, class D
> class iterator_facade
;
47 // A binary metafunction class that always returns bool. VC6
48 // ICEs on mpl::always<bool>, probably because of the default
52 template <class T
, class U
>
60 // enable if for use in operator implementation.
67 struct enable_if_interoperable
68 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
70 typedef typename
mpl::if_
<
72 is_convertible
<Facade1
, Facade2
>
73 , is_convertible
<Facade2
, Facade1
>
80 : ::boost::iterators::enable_if
<
82 is_convertible
<Facade1
, Facade2
>
83 , is_convertible
<Facade2
, Facade1
>
91 // Generates associated types for an iterator_facade with the
96 , class CategoryOrTraversal
100 struct iterator_facade_types
102 typedef typename facade_iterator_category
<
103 CategoryOrTraversal
, ValueParam
, Reference
104 >::type iterator_category
;
106 typedef typename remove_const
<ValueParam
>::type value_type
;
108 typedef typename
mpl::eval_if
<
109 boost::detail::iterator_writability_disabled
<ValueParam
,Reference
>
110 , add_pointer
<const value_type
>
111 , add_pointer
<value_type
>
114 # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
115 && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
116 || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
117 || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \
118 || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310)
120 // To interoperate with some broken library/compiler
121 // combinations, user-defined iterators must be derived from
122 // std::iterator. It is possible to implement a standard
123 // library for broken compilers without this limitation.
124 # define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
127 iterator
<iterator_category
, value_type
, Difference
, pointer
, Reference
>
132 // iterators whose dereference operators reference the same value
133 // for all iterators into the same sequence (like many input
134 // iterators) need help with their postfix ++: the referenced
135 // value must be read and stored away before the increment occurs
136 // so that *a++ yields the originally referenced element and not
138 template <class Iterator
>
139 class postfix_increment_proxy
141 typedef typename iterator_value
<Iterator
>::type value_type
;
143 explicit postfix_increment_proxy(Iterator
const& x
)
147 // Returning a mutable reference allows nonsense like
148 // (*r++).mutate(), but it imposes fewer assumptions about the
149 // behavior of the value_type. In particular, recall taht
150 // (*r).mutate() is legal if operator* returns by value.
154 return this->stored_value
;
157 mutable value_type stored_value
;
161 // In general, we can't determine that such an iterator isn't
162 // writable -- we also need to store a copy of the old iterator so
163 // that it can be written into.
164 template <class Iterator
>
165 class writable_postfix_increment_proxy
167 typedef typename iterator_value
<Iterator
>::type value_type
;
169 explicit writable_postfix_increment_proxy(Iterator
const& x
)
174 // Dereferencing must return a proxy so that both *r++ = o and
175 // value_type(*r++) can work. In this case, *r is the same as
176 // *r++, and the conversion operator below is used to ensure
178 writable_postfix_increment_proxy
const&
184 // Provides readability of *r++
185 operator value_type
&() const
190 // Provides writability of *r++
192 T
const& operator=(T
const& x
) const
194 *this->stored_iterator
= x
;
198 // This overload just in case only non-const objects are writable
200 T
& operator=(T
& x
) const
202 *this->stored_iterator
= x
;
207 operator Iterator
const&() const
209 return stored_iterator
;
213 mutable value_type stored_value
;
214 Iterator stored_iterator
;
217 # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
219 template <class Reference
, class Value
>
220 struct is_non_proxy_reference_impl
225 static typename
mpl::if_
<
228 , Value
const volatile*
232 >::type
& helper(R
const&);
234 BOOST_STATIC_CONSTANT(bool, value
= sizeof(helper(r
)) == 1);
237 template <class Reference
, class Value
>
238 struct is_non_proxy_reference
240 is_non_proxy_reference_impl
<Reference
, Value
>::value
244 template <class Reference
, class Value
>
245 struct is_non_proxy_reference
247 typename remove_reference
<Reference
>::type
249 , Value
const volatile*
254 // A metafunction to choose the result type of postfix ++
256 // Because the C++98 input iterator requirements say that *r++ has
257 // type T (value_type), implementations of some standard
258 // algorithms like lexicographical_compare may use constructions
263 // If *r++ returns a proxy (as required if r is writable but not
264 // multipass), this sort of expression will fail unless the proxy
265 // supports the operator<. Since there are any number of such
266 // operations, we're not going to try to support them. Therefore,
267 // even if r++ returns a proxy, *r++ will only return a proxy if
268 // *r also returns a proxy.
269 template <class Iterator
, class Value
, class Reference
, class CategoryOrTraversal
>
270 struct postfix_increment_result
273 // A proxy is only needed for readable iterators
274 is_convertible
<Reference
,Value
const&>
276 // No multipass iterator can have values that disappear
277 // before positions can be re-visited
280 typename iterator_category_to_traversal
<CategoryOrTraversal
>::type
281 , forward_traversal_tag
286 is_non_proxy_reference
<Reference
,Value
>
287 , postfix_increment_proxy
<Iterator
>
288 , writable_postfix_increment_proxy
<Iterator
>
290 , mpl::identity
<Iterator
>
294 // operator->() needs special support for input iterators to strictly meet the
295 // standard's requirements. If *i is not a reference type, we must still
296 // produce a lvalue to which a pointer can be formed. We do that by
297 // returning an instantiation of this special proxy class template.
299 struct operator_arrow_proxy
301 operator_arrow_proxy(T
const* px
) : m_value(*px
) {}
302 T
* operator->() const { return &m_value
; }
303 // This function is needed for MWCW and BCC, which won't call operator->
304 // again automatically per 13.3.1.2 para 8
305 operator T
*() const { return &m_value
; }
309 // A metafunction that gets the result type for operator->. Also
310 // has a static function make() which builds the result from a
312 template <class ValueType
, class Reference
, class Pointer
>
313 struct operator_arrow_result
315 // CWPro8.3 won't accept "operator_arrow_result::type", and we
316 // need that type below, so metafunction forwarding would be a
317 // losing proposition here.
318 typedef typename
mpl::if_
<
319 is_reference
<Reference
>
321 , operator_arrow_proxy
<ValueType
>
324 static type
make(Reference x
)
326 return implicit_cast
<type
>(&x
);
330 # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
333 struct operator_arrow_result
<int, int, int>
339 // A proxy return type for operator[], needed to deal with
340 // iterators that may invalidate referents upon destruction.
341 // Consider the temporary iterator in *(a + n)
342 template <class Iterator
>
343 class operator_brackets_proxy
345 // Iterator is actually an iterator_facade, so we do not have to
346 // go through iterator_traits to access the traits.
347 typedef typename
Iterator::reference reference
;
348 typedef typename
Iterator::value_type value_type
;
351 operator_brackets_proxy(Iterator
const& iter
)
355 operator reference() const
360 operator_brackets_proxy
& operator=(value_type
const& val
)
370 // A metafunction that determines whether operator[] must return a
371 // proxy, or whether it can simply return a copy of the value_type.
372 template <class ValueType
, class Reference
>
373 struct use_operator_brackets_proxy
376 // Really we want an is_copy_constructible trait here,
377 // but is_POD will have to suffice in the meantime.
378 boost::is_POD
<ValueType
>
379 , iterator_writability_disabled
<ValueType
,Reference
>
384 template <class Iterator
, class Value
, class Reference
>
385 struct operator_brackets_result
387 typedef typename
mpl::if_
<
388 use_operator_brackets_proxy
<Value
,Reference
>
389 , operator_brackets_proxy
<Iterator
>
394 template <class Iterator
>
395 operator_brackets_proxy
<Iterator
> make_operator_brackets_result(Iterator
const& iter
, mpl::true_
)
397 return operator_brackets_proxy
<Iterator
>(iter
);
400 template <class Iterator
>
401 typename
Iterator::value_type
make_operator_brackets_result(Iterator
const& iter
, mpl::false_
)
406 struct choose_difference_type
408 template <class I1
, class I2
>
411 # ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
412 iterator_difference
<I1
>
413 # elif BOOST_WORKAROUND(BOOST_MSVC, < 1300)
415 is_convertible
<I2
,I1
>
416 , typename
I1::difference_type
417 , typename
I2::difference_type
421 is_convertible
<I2
,I1
>
422 , iterator_difference
<I1
>
423 , iterator_difference
<I2
>
429 } // namespace detail
432 // Macros which describe the declarations of binary operators
433 # ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
434 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
436 class Derived1, class V1, class TC1, class Reference1, class Difference1 \
437 , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
439 prefix typename mpl::apply2<result_type,Derived1,Derived2>::type \
441 iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
442 , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
444 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
446 class Derived1, class V1, class TC1, class Reference1, class Difference1 \
447 , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
449 prefix typename boost::detail::enable_if_interoperable< \
451 , typename mpl::apply2<result_type,Derived1,Derived2>::type \
454 iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
455 , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
458 # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
459 template <class Derived, class V, class TC, class R, class D> \
460 prefix Derived operator+ args
463 // Helper class for granting access to the iterator core interface.
465 // The simple core interface is used by iterator_facade. The core
466 // interface of a user/library defined iterator type should not be made public
467 // so that it does not clutter the public interface. Instead iterator_core_access
468 // should be made friend so that iterator_facade can access the core
469 // interface through iterator_core_access.
471 class iterator_core_access
473 # if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
474 // Tasteless as this may seem, making all members public allows member templates
475 // to work in the absence of member template friends.
479 template <class I
, class V
, class TC
, class R
, class D
> friend class iterator_facade
;
481 # define BOOST_ITERATOR_FACADE_RELATION(op) \
482 BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::detail::always_bool2);
484 BOOST_ITERATOR_FACADE_RELATION(==)
485 BOOST_ITERATOR_FACADE_RELATION(!=)
487 BOOST_ITERATOR_FACADE_RELATION(<)
488 BOOST_ITERATOR_FACADE_RELATION(>)
489 BOOST_ITERATOR_FACADE_RELATION(<=)
490 BOOST_ITERATOR_FACADE_RELATION(>=)
491 # undef BOOST_ITERATOR_FACADE_RELATION
493 BOOST_ITERATOR_FACADE_INTEROP_HEAD(
494 friend, -, boost::detail::choose_difference_type
)
497 BOOST_ITERATOR_FACADE_PLUS_HEAD(
499 , (iterator_facade
<Derived
, V
, TC
, R
, D
> const&
500 , typename
Derived::difference_type
)
504 BOOST_ITERATOR_FACADE_PLUS_HEAD(
506 , (typename
Derived::difference_type
507 , iterator_facade
<Derived
, V
, TC
, R
, D
> const&)
513 template <class Facade
>
514 static typename
Facade::reference
dereference(Facade
const& f
)
516 return f
.dereference();
519 template <class Facade
>
520 static void increment(Facade
& f
)
525 template <class Facade
>
526 static void decrement(Facade
& f
)
531 template <class Facade1
, class Facade2
>
532 static bool equal(Facade1
const& f1
, Facade2
const& f2
, mpl::true_
)
537 template <class Facade1
, class Facade2
>
538 static bool equal(Facade1
const& f1
, Facade2
const& f2
, mpl::false_
)
543 template <class Facade
>
544 static void advance(Facade
& f
, typename
Facade::difference_type n
)
549 template <class Facade1
, class Facade2
>
550 static typename
Facade1::difference_type
distance_from(
551 Facade1
const& f1
, Facade2
const& f2
, mpl::true_
)
553 return -f1
.distance_to(f2
);
556 template <class Facade1
, class Facade2
>
557 static typename
Facade2::difference_type
distance_from(
558 Facade1
const& f1
, Facade2
const& f2
, mpl::false_
)
560 return f2
.distance_to(f1
);
564 // Curiously Recurring Template interface.
566 template <class I
, class V
, class TC
, class R
, class D
>
567 static I
& derived(iterator_facade
<I
,V
,TC
,R
,D
>& facade
)
569 return *static_cast<I
*>(&facade
);
572 template <class I
, class V
, class TC
, class R
, class D
>
573 static I
const& derived(iterator_facade
<I
,V
,TC
,R
,D
> const& facade
)
575 return *static_cast<I
const*>(&facade
);
579 // objects of this class are useless
580 iterator_core_access(); //undefined
584 // iterator_facade - use as a public base class for defining new
585 // standard-conforming iterators.
588 class Derived
// The derived iterator type being constructed
590 , class CategoryOrTraversal
591 , class Reference
= Value
&
592 , class Difference
= std::ptrdiff_t
594 class iterator_facade
595 # ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
596 : public boost::detail::iterator_facade_types
<
597 Value
, CategoryOrTraversal
, Reference
, Difference
599 # undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
604 // Curiously Recurring Template interface.
608 return *static_cast<Derived
*>(this);
611 Derived
const& derived() const
613 return *static_cast<Derived
const*>(this);
616 typedef boost::detail::iterator_facade_types
<
617 Value
, CategoryOrTraversal
, Reference
, Difference
621 // For use by derived classes
622 typedef iterator_facade
<Derived
,Value
,CategoryOrTraversal
,Reference
,Difference
> iterator_facade_
;
626 typedef typename
associated_types::value_type value_type
;
627 typedef Reference reference
;
628 typedef Difference difference_type
;
629 typedef typename
associated_types::pointer pointer
;
630 typedef typename
associated_types::iterator_category iterator_category
;
632 reference
operator*() const
634 return iterator_core_access::dereference(this->derived());
637 typename
boost::detail::operator_arrow_result
<
644 return boost::detail::operator_arrow_result
<
648 >::make(*this->derived());
651 typename
boost::detail::operator_brackets_result
<Derived
,Value
,reference
>::type
652 operator[](difference_type n
) const
654 typedef boost::detail::use_operator_brackets_proxy
<Value
,Reference
> use_proxy
;
656 return boost::detail::make_operator_brackets_result
<Derived
>(
662 Derived
& operator++()
664 iterator_core_access::increment(this->derived());
665 return this->derived();
668 # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
669 typename
boost::detail::postfix_increment_result
<Derived
,Value
,Reference
,CategoryOrTraversal
>::type
672 typename
boost::detail::postfix_increment_result
<Derived
,Value
,Reference
,CategoryOrTraversal
>::type
673 tmp(this->derived());
679 Derived
& operator--()
681 iterator_core_access::decrement(this->derived());
682 return this->derived();
685 Derived
operator--(int)
687 Derived
tmp(this->derived());
692 Derived
& operator+=(difference_type n
)
694 iterator_core_access::advance(this->derived(), n
);
695 return this->derived();
698 Derived
& operator-=(difference_type n
)
700 iterator_core_access::advance(this->derived(), -n
);
701 return this->derived();
704 Derived
operator-(difference_type x
) const
706 Derived
result(this->derived());
710 # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
711 // There appears to be a bug which trashes the data of classes
712 // derived from iterator_facade when they are assigned unless we
713 // define this assignment operator. This bug is only revealed
714 // (so far) in STLPort debug mode, but it's clearly a codegen
715 // problem so we apply the workaround for all MSVC6.
716 iterator_facade
& operator=(iterator_facade
const&)
723 # if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
724 template <class I
, class V
, class TC
, class R
, class D
>
725 inline typename
boost::detail::postfix_increment_result
<I
,V
,R
,TC
>::type
727 iterator_facade
<I
,V
,TC
,R
,D
>& i
731 typename
boost::detail::postfix_increment_result
<I
,V
,R
,TC
>::type
732 tmp(*static_cast<I
*>(&i
));
742 // Comparison operator implementation. The library supplied operators
743 // enables the user to provide fully interoperable constant/mutable
744 // iterator types. I.e. the library provides all operators
745 // for all mutable/constant iterator combinations.
747 // Note though that this kind of interoperability for constant/mutable
748 // iterators is not required by the standard for container iterators.
749 // All the standard asks for is a conversion mutable -> constant.
750 // Most standard library implementations nowadays provide fully interoperable
751 // iterator implementations, but there are still heavily used implementations
752 // that do not provide them. (Actually it's even worse, they do not provide
753 // them for only a few iterators.)
755 // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should
756 // enable the user to turn off mixed type operators
758 // The library takes care to provide only the right operator overloads.
761 // bool operator==(Iterator, Iterator);
762 // bool operator==(ConstIterator, Iterator);
763 // bool operator==(Iterator, ConstIterator);
764 // bool operator==(ConstIterator, ConstIterator);
768 // In order to do so it uses c++ idioms that are not yet widely supported
769 // by current compiler releases. The library is designed to degrade gracefully
770 // in the face of compiler deficiencies. In general compiler
771 // deficiencies result in less strict error checking and more obscure
772 // error messages, functionality is not affected.
774 // For full operation compiler support for "Substitution Failure Is Not An Error"
775 // (aka. enable_if) and boost::is_convertible is required.
777 // The following problems occur if support is lacking.
782 // AdaptorA<Iterator1> a1;
783 // AdaptorA<Iterator2> a2;
785 // // This will result in a no such overload error in full operation
786 // // If enable_if or is_convertible is not supported
787 // // The instantiation will fail with an error hopefully indicating that
788 // // there is no operator== for Iterator1, Iterator2
789 // // The same will happen if no enable_if is used to remove
790 // // false overloads from the templated conversion constructor
796 // AdaptorA<Iterator> a;
797 // AdaptorB<Iterator> b;
799 // // This will result in a no such overload error in full operation
800 // // If enable_if is not supported the static assert used
801 // // in the operator implementation will fail.
802 // // This will accidently work if is_convertible is not supported.
808 # ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
809 # define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_()
811 # define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible<a,b>()
814 # define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \
815 BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \
817 /* For those compilers that do not support enable_if */ \
818 BOOST_STATIC_ASSERT(( \
819 is_interoperable< Derived1, Derived2 >::value \
821 return_prefix iterator_core_access::base_op( \
822 *static_cast<Derived1 const*>(&lhs) \
823 , *static_cast<Derived2 const*>(&rhs) \
824 , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
828 # define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
829 BOOST_ITERATOR_FACADE_INTEROP( \
831 , boost::detail::always_bool2 \
836 BOOST_ITERATOR_FACADE_RELATION(==, return, equal
)
837 BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal
)
839 BOOST_ITERATOR_FACADE_RELATION(<, return 0 >, distance_from
)
840 BOOST_ITERATOR_FACADE_RELATION(>, return 0 <, distance_from
)
841 BOOST_ITERATOR_FACADE_RELATION(<=, return 0 >=, distance_from
)
842 BOOST_ITERATOR_FACADE_RELATION(>=, return 0 <=, distance_from
)
843 # undef BOOST_ITERATOR_FACADE_RELATION
845 // operator- requires an additional part in the static assertion
846 BOOST_ITERATOR_FACADE_INTEROP(
848 , boost::detail::choose_difference_type
852 # undef BOOST_ITERATOR_FACADE_INTEROP
853 # undef BOOST_ITERATOR_FACADE_INTEROP_HEAD
855 # define BOOST_ITERATOR_FACADE_PLUS(args) \
856 BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \
858 Derived tmp(static_cast<Derived const&>(i)); \
862 BOOST_ITERATOR_FACADE_PLUS((
863 iterator_facade
<Derived
, V
, TC
, R
, D
> const& i
864 , typename
Derived::difference_type n
867 BOOST_ITERATOR_FACADE_PLUS((
868 typename
Derived::difference_type n
869 , iterator_facade
<Derived
, V
, TC
, R
, D
> const& i
871 # undef BOOST_ITERATOR_FACADE_PLUS
872 # undef BOOST_ITERATOR_FACADE_PLUS_HEAD
876 #include <boost/iterator/detail/config_undef.hpp>
878 #endif // BOOST_ITERATOR_FACADE_23022003THW_HPP