Chris@16: // (C) Copyright David Abrahams 2002. Chris@16: // (C) Copyright Jeremy Siek 2002. Chris@16: // (C) Copyright Thomas Witt 2002. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: #ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP Chris@16: #define BOOST_ITERATOR_FACADE_23022003THW_HPP Chris@16: Chris@101: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include // this goes last Chris@16: Chris@101: namespace boost { Chris@101: namespace iterators { Chris@101: Chris@16: // This forward declaration is required for the friend declaration Chris@16: // in iterator_core_access Chris@16: template class iterator_facade; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: // A binary metafunction class that always returns bool. VC6 Chris@16: // ICEs on mpl::always, probably because of the default Chris@16: // parameters. Chris@16: struct always_bool2 Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef bool type; Chris@16: }; Chris@16: }; Chris@16: Chris@101: // The type trait checks if the category or traversal is at least as advanced as the specified required traversal Chris@101: template< typename CategoryOrTraversal, typename Required > Chris@101: struct is_traversal_at_least : Chris@101: public boost::is_convertible< typename iterator_category_to_traversal< CategoryOrTraversal >::type, Required > Chris@101: {}; Chris@101: Chris@16: // Chris@16: // enable if for use in operator implementation. Chris@16: // Chris@16: template < Chris@16: class Facade1 Chris@16: , class Facade2 Chris@16: , class Return Chris@16: > Chris@101: struct enable_if_interoperable : Chris@101: public boost::iterators::enable_if< Chris@101: is_interoperable< Facade1, Facade2 > Chris@101: , Return Chris@101: > Chris@101: {}; Chris@101: Chris@101: // Chris@101: // enable if for use in implementation of operators specific for random access traversal. Chris@101: // Chris@101: template < Chris@101: class Facade1 Chris@101: , class Facade2 Chris@101: , class Return Chris@101: > Chris@101: struct enable_if_interoperable_and_random_access_traversal : Chris@101: public boost::iterators::enable_if< Chris@101: mpl::and_< Chris@101: is_interoperable< Facade1, Facade2 > Chris@101: , is_traversal_at_least< typename iterator_category< Facade1 >::type, random_access_traversal_tag > Chris@101: , is_traversal_at_least< typename iterator_category< Facade2 >::type, random_access_traversal_tag > Chris@16: > Chris@16: , Return Chris@16: > Chris@16: {}; Chris@16: Chris@16: // Chris@16: // Generates associated types for an iterator_facade with the Chris@16: // given parameters. Chris@16: // Chris@16: template < Chris@16: class ValueParam Chris@16: , class CategoryOrTraversal Chris@101: , class Reference Chris@16: , class Difference Chris@16: > Chris@16: struct iterator_facade_types Chris@16: { Chris@16: typedef typename facade_iterator_category< Chris@16: CategoryOrTraversal, ValueParam, Reference Chris@16: >::type iterator_category; Chris@101: Chris@16: typedef typename remove_const::type value_type; Chris@101: Chris@16: // Not the real associated pointer type Chris@16: typedef typename mpl::eval_if< Chris@101: boost::iterators::detail::iterator_writability_disabled Chris@16: , add_pointer Chris@16: , add_pointer Chris@16: >::type pointer; Chris@101: Chris@16: # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ Chris@16: && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ Chris@16: || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ Chris@16: || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \ Chris@16: || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310) Chris@16: Chris@16: // To interoperate with some broken library/compiler Chris@16: // combinations, user-defined iterators must be derived from Chris@16: // std::iterator. It is possible to implement a standard Chris@16: // library for broken compilers without this limitation. Chris@16: # define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1 Chris@16: Chris@16: typedef Chris@16: iterator Chris@16: base; Chris@16: # endif Chris@16: }; Chris@16: Chris@16: // iterators whose dereference operators reference the same value Chris@16: // for all iterators into the same sequence (like many input Chris@16: // iterators) need help with their postfix ++: the referenced Chris@16: // value must be read and stored away before the increment occurs Chris@16: // so that *a++ yields the originally referenced element and not Chris@16: // the next one. Chris@16: template Chris@16: class postfix_increment_proxy Chris@16: { Chris@16: typedef typename iterator_value::type value_type; Chris@16: public: Chris@16: explicit postfix_increment_proxy(Iterator const& x) Chris@16: : stored_value(*x) Chris@16: {} Chris@16: Chris@16: // Returning a mutable reference allows nonsense like Chris@16: // (*r++).mutate(), but it imposes fewer assumptions about the Chris@16: // behavior of the value_type. In particular, recall that Chris@16: // (*r).mutate() is legal if operator* returns by value. Chris@16: value_type& Chris@16: operator*() const Chris@16: { Chris@16: return this->stored_value; Chris@16: } Chris@16: private: Chris@16: mutable value_type stored_value; Chris@16: }; Chris@101: Chris@16: // Chris@16: // In general, we can't determine that such an iterator isn't Chris@16: // writable -- we also need to store a copy of the old iterator so Chris@16: // that it can be written into. Chris@16: template Chris@16: class writable_postfix_increment_proxy Chris@16: { Chris@16: typedef typename iterator_value::type value_type; Chris@16: public: Chris@16: explicit writable_postfix_increment_proxy(Iterator const& x) Chris@16: : stored_value(*x) Chris@16: , stored_iterator(x) Chris@16: {} Chris@16: Chris@16: // Dereferencing must return a proxy so that both *r++ = o and Chris@16: // value_type(*r++) can work. In this case, *r is the same as Chris@16: // *r++, and the conversion operator below is used to ensure Chris@16: // readability. Chris@16: writable_postfix_increment_proxy const& Chris@16: operator*() const Chris@16: { Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Provides readability of *r++ Chris@16: operator value_type&() const Chris@16: { Chris@16: return stored_value; Chris@16: } Chris@16: Chris@16: // Provides writability of *r++ Chris@16: template Chris@16: T const& operator=(T const& x) const Chris@16: { Chris@16: *this->stored_iterator = x; Chris@16: return x; Chris@16: } Chris@16: Chris@16: // This overload just in case only non-const objects are writable Chris@16: template Chris@16: T& operator=(T& x) const Chris@16: { Chris@16: *this->stored_iterator = x; Chris@16: return x; Chris@16: } Chris@16: Chris@16: // Provides X(r++) Chris@16: operator Iterator const&() const Chris@16: { Chris@16: return stored_iterator; Chris@16: } Chris@101: Chris@16: private: Chris@16: mutable value_type stored_value; Chris@16: Iterator stored_iterator; Chris@16: }; Chris@16: Chris@16: # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Chris@16: Chris@16: template Chris@16: struct is_non_proxy_reference_impl Chris@16: { Chris@16: static Reference r; Chris@101: Chris@16: template Chris@16: static typename mpl::if_< Chris@16: is_convertible< Chris@16: R const volatile* Chris@16: , Value const volatile* Chris@16: > Chris@16: , char[1] Chris@16: , char[2] Chris@16: >::type& helper(R const&); Chris@101: Chris@16: BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1); Chris@16: }; Chris@101: Chris@16: template Chris@16: struct is_non_proxy_reference Chris@16: : mpl::bool_< Chris@16: is_non_proxy_reference_impl::value Chris@16: > Chris@16: {}; Chris@101: # else Chris@16: template Chris@16: struct is_non_proxy_reference Chris@16: : is_convertible< Chris@16: typename remove_reference::type Chris@16: const volatile* Chris@16: , Value const volatile* Chris@16: > Chris@16: {}; Chris@101: # endif Chris@101: Chris@16: // A metafunction to choose the result type of postfix ++ Chris@16: // Chris@16: // Because the C++98 input iterator requirements say that *r++ has Chris@16: // type T (value_type), implementations of some standard Chris@16: // algorithms like lexicographical_compare may use constructions Chris@16: // like: Chris@16: // Chris@16: // *r++ < *s++ Chris@16: // Chris@16: // If *r++ returns a proxy (as required if r is writable but not Chris@16: // multipass), this sort of expression will fail unless the proxy Chris@16: // supports the operator<. Since there are any number of such Chris@16: // operations, we're not going to try to support them. Therefore, Chris@16: // even if r++ returns a proxy, *r++ will only return a proxy if Chris@16: // *r also returns a proxy. Chris@16: template Chris@16: struct postfix_increment_result Chris@16: : mpl::eval_if< Chris@16: mpl::and_< Chris@16: // A proxy is only needed for readable iterators Chris@16: is_convertible Chris@101: Chris@16: // No multipass iterator can have values that disappear Chris@16: // before positions can be re-visited Chris@16: , mpl::not_< Chris@16: is_convertible< Chris@16: typename iterator_category_to_traversal::type Chris@16: , forward_traversal_tag Chris@16: > Chris@16: > Chris@16: > Chris@16: , mpl::if_< Chris@16: is_non_proxy_reference Chris@16: , postfix_increment_proxy Chris@16: , writable_postfix_increment_proxy Chris@16: > Chris@16: , mpl::identity Chris@16: > Chris@16: {}; Chris@16: Chris@16: // operator->() needs special support for input iterators to strictly meet the Chris@16: // standard's requirements. If *i is not a reference type, we must still Chris@16: // produce an lvalue to which a pointer can be formed. We do that by Chris@16: // returning a proxy object containing an instance of the reference object. Chris@16: template Chris@16: struct operator_arrow_dispatch // proxy references Chris@16: { Chris@16: struct proxy Chris@16: { Chris@16: explicit proxy(Reference const & x) : m_ref(x) {} Chris@16: Reference* operator->() { return boost::addressof(m_ref); } Chris@16: // This function is needed for MWCW and BCC, which won't call Chris@16: // operator-> again automatically per 13.3.1.2 para 8 Chris@16: operator Reference*() { return boost::addressof(m_ref); } Chris@16: Reference m_ref; Chris@16: }; Chris@16: typedef proxy result_type; Chris@16: static result_type apply(Reference const & x) Chris@16: { Chris@16: return result_type(x); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct operator_arrow_dispatch // "real" references Chris@16: { Chris@16: typedef Pointer result_type; Chris@16: static result_type apply(T& x) Chris@16: { Chris@16: return boost::addressof(x); Chris@16: } Chris@16: }; Chris@16: Chris@16: // A proxy return type for operator[], needed to deal with Chris@16: // iterators that may invalidate referents upon destruction. Chris@16: // Consider the temporary iterator in *(a + n) Chris@16: template Chris@16: class operator_brackets_proxy Chris@16: { Chris@16: // Iterator is actually an iterator_facade, so we do not have to Chris@16: // go through iterator_traits to access the traits. Chris@16: typedef typename Iterator::reference reference; Chris@16: typedef typename Iterator::value_type value_type; Chris@16: Chris@16: public: Chris@16: operator_brackets_proxy(Iterator const& iter) Chris@16: : m_iter(iter) Chris@16: {} Chris@16: Chris@16: operator reference() const Chris@16: { Chris@16: return *m_iter; Chris@16: } Chris@16: Chris@16: operator_brackets_proxy& operator=(value_type const& val) Chris@16: { Chris@16: *m_iter = val; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: private: Chris@16: Iterator m_iter; Chris@16: }; Chris@16: Chris@16: // A metafunction that determines whether operator[] must return a Chris@16: // proxy, or whether it can simply return a copy of the value_type. Chris@16: template Chris@16: struct use_operator_brackets_proxy Chris@16: : mpl::not_< Chris@16: mpl::and_< Chris@16: // Really we want an is_copy_constructible trait here, Chris@16: // but is_POD will have to suffice in the meantime. Chris@16: boost::is_POD Chris@16: , iterator_writability_disabled Chris@16: > Chris@16: > Chris@16: {}; Chris@101: Chris@16: template Chris@16: struct operator_brackets_result Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: use_operator_brackets_proxy Chris@16: , operator_brackets_proxy Chris@16: , Value Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: operator_brackets_proxy make_operator_brackets_result(Iterator const& iter, mpl::true_) Chris@16: { Chris@16: return operator_brackets_proxy(iter); Chris@16: } Chris@16: Chris@16: template Chris@16: typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_) Chris@16: { Chris@16: return *iter; Chris@16: } Chris@16: Chris@16: struct choose_difference_type Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: : Chris@16: # ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP Chris@16: iterator_difference Chris@101: # else Chris@16: mpl::eval_if< Chris@16: is_convertible Chris@16: , iterator_difference Chris@16: , iterator_difference Chris@16: > Chris@101: # endif Chris@16: {}; Chris@16: Chris@16: }; Chris@101: Chris@101: template < Chris@101: class Derived Chris@101: , class Value Chris@101: , class CategoryOrTraversal Chris@101: , class Reference Chris@101: , class Difference Chris@101: , bool IsBidirectionalTraversal Chris@101: , bool IsRandomAccessTraversal Chris@101: > Chris@101: class iterator_facade_base; Chris@101: Chris@16: } // namespace detail Chris@16: Chris@16: Chris@16: // Macros which describe the declarations of binary operators Chris@16: # ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY Chris@101: # define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \ Chris@16: template < \ Chris@16: class Derived1, class V1, class TC1, class Reference1, class Difference1 \ Chris@16: , class Derived2, class V2, class TC2, class Reference2, class Difference2 \ Chris@16: > \ Chris@16: prefix typename mpl::apply2::type \ Chris@16: operator op( \ Chris@16: iterator_facade const& lhs \ Chris@16: , iterator_facade const& rhs) Chris@101: # else Chris@101: # define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \ Chris@16: template < \ Chris@16: class Derived1, class V1, class TC1, class Reference1, class Difference1 \ Chris@16: , class Derived2, class V2, class TC2, class Reference2, class Difference2 \ Chris@16: > \ Chris@101: prefix typename enabler< \ Chris@16: Derived1, Derived2 \ Chris@16: , typename mpl::apply2::type \ Chris@16: >::type \ Chris@16: operator op( \ Chris@16: iterator_facade const& lhs \ Chris@16: , iterator_facade const& rhs) Chris@101: # endif Chris@101: Chris@101: # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ Chris@101: BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable) Chris@101: Chris@101: # define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(prefix, op, result_type) \ Chris@101: BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable_and_random_access_traversal) Chris@16: Chris@16: # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ Chris@16: template \ Chris@101: prefix typename boost::iterators::enable_if< \ Chris@101: boost::iterators::detail::is_traversal_at_least< TC, boost::iterators::random_access_traversal_tag >, \ Chris@101: Derived \ Chris@101: >::type operator+ args Chris@16: Chris@16: // Chris@16: // Helper class for granting access to the iterator core interface. Chris@16: // Chris@16: // The simple core interface is used by iterator_facade. The core Chris@16: // interface of a user/library defined iterator type should not be made public Chris@16: // so that it does not clutter the public interface. Instead iterator_core_access Chris@16: // should be made friend so that iterator_facade can access the core Chris@16: // interface through iterator_core_access. Chris@16: // Chris@16: class iterator_core_access Chris@16: { Chris@101: # if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: // Tasteless as this may seem, making all members public allows member templates Chris@16: // to work in the absence of member template friends. Chris@16: public: Chris@16: # else Chris@101: Chris@16: template friend class iterator_facade; Chris@101: template Chris@101: friend class detail::iterator_facade_base; Chris@16: Chris@16: # define BOOST_ITERATOR_FACADE_RELATION(op) \ Chris@101: BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::iterators::detail::always_bool2); Chris@16: Chris@16: BOOST_ITERATOR_FACADE_RELATION(==) Chris@16: BOOST_ITERATOR_FACADE_RELATION(!=) Chris@16: Chris@16: # undef BOOST_ITERATOR_FACADE_RELATION Chris@16: Chris@101: # define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op) \ Chris@101: BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(friend,op, boost::iterators::detail::always_bool2); Chris@101: Chris@101: BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<) Chris@101: BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>) Chris@101: BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=) Chris@101: BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=) Chris@101: Chris@101: # undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION Chris@101: Chris@101: BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD( Chris@101: friend, -, boost::iterators::detail::choose_difference_type) Chris@16: ; Chris@16: Chris@16: BOOST_ITERATOR_FACADE_PLUS_HEAD( Chris@16: friend inline Chris@101: , (iterator_facade const& Chris@101: , typename Derived::difference_type) Chris@16: ) Chris@16: ; Chris@16: Chris@16: BOOST_ITERATOR_FACADE_PLUS_HEAD( Chris@16: friend inline Chris@16: , (typename Derived::difference_type Chris@101: , iterator_facade const&) Chris@16: ) Chris@16: ; Chris@16: Chris@16: # endif Chris@16: Chris@16: template Chris@16: static typename Facade::reference dereference(Facade const& f) Chris@16: { Chris@16: return f.dereference(); Chris@16: } Chris@16: Chris@16: template Chris@16: static void increment(Facade& f) Chris@16: { Chris@16: f.increment(); Chris@16: } Chris@16: Chris@16: template Chris@16: static void decrement(Facade& f) Chris@16: { Chris@16: f.decrement(); Chris@16: } Chris@16: Chris@16: template Chris@16: static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_) Chris@16: { Chris@16: return f1.equal(f2); Chris@16: } Chris@16: Chris@16: template Chris@16: static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_) Chris@16: { Chris@16: return f2.equal(f1); Chris@16: } Chris@16: Chris@16: template Chris@16: static void advance(Facade& f, typename Facade::difference_type n) Chris@16: { Chris@16: f.advance(n); Chris@16: } Chris@16: Chris@16: template Chris@16: static typename Facade1::difference_type distance_from( Chris@16: Facade1 const& f1, Facade2 const& f2, mpl::true_) Chris@16: { Chris@16: return -f1.distance_to(f2); Chris@16: } Chris@16: Chris@16: template Chris@16: static typename Facade2::difference_type distance_from( Chris@16: Facade1 const& f1, Facade2 const& f2, mpl::false_) Chris@16: { Chris@16: return f2.distance_to(f1); Chris@16: } Chris@16: Chris@16: // Chris@16: // Curiously Recurring Template interface. Chris@16: // Chris@16: template Chris@16: static I& derived(iterator_facade& facade) Chris@16: { Chris@16: return *static_cast(&facade); Chris@16: } Chris@16: Chris@16: template Chris@16: static I const& derived(iterator_facade const& facade) Chris@16: { Chris@16: return *static_cast(&facade); Chris@16: } Chris@16: Chris@16: // objects of this class are useless Chris@101: BOOST_DELETED_FUNCTION(iterator_core_access()) Chris@16: }; Chris@16: Chris@101: namespace detail { Chris@101: Chris@101: // Implementation for forward traversal iterators Chris@101: template < Chris@101: class Derived Chris@101: , class Value Chris@101: , class CategoryOrTraversal Chris@101: , class Reference Chris@101: , class Difference Chris@101: > Chris@101: class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false > Chris@101: # ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE Chris@101: : public boost::iterators::detail::iterator_facade_types< Chris@101: Value, CategoryOrTraversal, Reference, Difference Chris@101: >::base Chris@101: # undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE Chris@101: # endif Chris@101: { Chris@101: private: Chris@101: typedef boost::iterators::detail::iterator_facade_types< Chris@101: Value, CategoryOrTraversal, Reference, Difference Chris@101: > associated_types; Chris@101: Chris@101: typedef boost::iterators::detail::operator_arrow_dispatch< Chris@101: Reference Chris@101: , typename associated_types::pointer Chris@101: > operator_arrow_dispatch_; Chris@101: Chris@101: public: Chris@101: typedef typename associated_types::value_type value_type; Chris@101: typedef Reference reference; Chris@101: typedef Difference difference_type; Chris@101: Chris@101: typedef typename operator_arrow_dispatch_::result_type pointer; Chris@101: Chris@101: typedef typename associated_types::iterator_category iterator_category; Chris@101: Chris@101: public: Chris@101: reference operator*() const Chris@101: { Chris@101: return iterator_core_access::dereference(this->derived()); Chris@101: } Chris@101: Chris@101: pointer operator->() const Chris@101: { Chris@101: return operator_arrow_dispatch_::apply(*this->derived()); Chris@101: } Chris@101: Chris@101: Derived& operator++() Chris@101: { Chris@101: iterator_core_access::increment(this->derived()); Chris@101: return this->derived(); Chris@101: } Chris@101: Chris@101: protected: Chris@101: // Chris@101: // Curiously Recurring Template interface. Chris@101: // Chris@101: Derived& derived() Chris@101: { Chris@101: return *static_cast(this); Chris@101: } Chris@101: Chris@101: Derived const& derived() const Chris@101: { Chris@101: return *static_cast(this); Chris@101: } Chris@101: }; Chris@101: Chris@101: // Implementation for bidirectional traversal iterators Chris@101: template < Chris@101: class Derived Chris@101: , class Value Chris@101: , class CategoryOrTraversal Chris@101: , class Reference Chris@101: , class Difference Chris@101: > Chris@101: class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > : Chris@101: public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false > Chris@101: { Chris@101: public: Chris@101: Derived& operator--() Chris@101: { Chris@101: iterator_core_access::decrement(this->derived()); Chris@101: return this->derived(); Chris@101: } Chris@101: Chris@101: Derived operator--(int) Chris@101: { Chris@101: Derived tmp(this->derived()); Chris@101: --*this; Chris@101: return tmp; Chris@101: } Chris@101: }; Chris@101: Chris@101: // Implementation for random access traversal iterators Chris@101: template < Chris@101: class Derived Chris@101: , class Value Chris@101: , class CategoryOrTraversal Chris@101: , class Reference Chris@101: , class Difference Chris@101: > Chris@101: class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, true > : Chris@101: public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > Chris@101: { Chris@101: private: Chris@101: typedef iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > base_type; Chris@101: Chris@101: public: Chris@101: typedef typename base_type::reference reference; Chris@101: typedef typename base_type::difference_type difference_type; Chris@101: Chris@101: public: Chris@101: typename boost::iterators::detail::operator_brackets_result::type Chris@101: operator[](difference_type n) const Chris@101: { Chris@101: typedef boost::iterators::detail::use_operator_brackets_proxy use_proxy; Chris@101: Chris@101: return boost::iterators::detail::make_operator_brackets_result( Chris@101: this->derived() + n Chris@101: , use_proxy() Chris@101: ); Chris@101: } Chris@101: Chris@101: Derived& operator+=(difference_type n) Chris@101: { Chris@101: iterator_core_access::advance(this->derived(), n); Chris@101: return this->derived(); Chris@101: } Chris@101: Chris@101: Derived& operator-=(difference_type n) Chris@101: { Chris@101: iterator_core_access::advance(this->derived(), -n); Chris@101: return this->derived(); Chris@101: } Chris@101: Chris@101: Derived operator-(difference_type x) const Chris@101: { Chris@101: Derived result(this->derived()); Chris@101: return result -= x; Chris@101: } Chris@101: }; Chris@101: Chris@101: } // namespace detail Chris@101: Chris@16: // Chris@16: // iterator_facade - use as a public base class for defining new Chris@16: // standard-conforming iterators. Chris@16: // Chris@16: template < Chris@16: class Derived // The derived iterator type being constructed Chris@16: , class Value Chris@16: , class CategoryOrTraversal Chris@16: , class Reference = Value& Chris@16: , class Difference = std::ptrdiff_t Chris@16: > Chris@101: class iterator_facade : Chris@101: public detail::iterator_facade_base< Chris@101: Derived, Chris@101: Value, Chris@101: CategoryOrTraversal, Chris@101: Reference, Chris@101: Difference, Chris@101: detail::is_traversal_at_least< CategoryOrTraversal, bidirectional_traversal_tag >::value, Chris@101: detail::is_traversal_at_least< CategoryOrTraversal, random_access_traversal_tag >::value Chris@101: > Chris@16: { Chris@101: protected: Chris@16: // For use by derived classes Chris@16: typedef iterator_facade iterator_facade_; Chris@16: }; Chris@16: Chris@16: template Chris@101: inline typename boost::iterators::detail::postfix_increment_result::type Chris@16: operator++( Chris@16: iterator_facade& i Chris@16: , int Chris@16: ) Chris@16: { Chris@101: typename boost::iterators::detail::postfix_increment_result::type Chris@16: tmp(*static_cast(&i)); Chris@101: Chris@16: ++i; Chris@101: Chris@16: return tmp; Chris@16: } Chris@16: Chris@101: Chris@16: // Chris@16: // Comparison operator implementation. The library supplied operators Chris@16: // enables the user to provide fully interoperable constant/mutable Chris@16: // iterator types. I.e. the library provides all operators Chris@16: // for all mutable/constant iterator combinations. Chris@16: // Chris@16: // Note though that this kind of interoperability for constant/mutable Chris@16: // iterators is not required by the standard for container iterators. Chris@16: // All the standard asks for is a conversion mutable -> constant. Chris@16: // Most standard library implementations nowadays provide fully interoperable Chris@16: // iterator implementations, but there are still heavily used implementations Chris@16: // that do not provide them. (Actually it's even worse, they do not provide Chris@16: // them for only a few iterators.) Chris@16: // Chris@16: // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should Chris@16: // enable the user to turn off mixed type operators Chris@16: // Chris@16: // The library takes care to provide only the right operator overloads. Chris@16: // I.e. Chris@16: // Chris@16: // bool operator==(Iterator, Iterator); Chris@16: // bool operator==(ConstIterator, Iterator); Chris@16: // bool operator==(Iterator, ConstIterator); Chris@16: // bool operator==(ConstIterator, ConstIterator); Chris@16: // Chris@16: // ... Chris@16: // Chris@16: // In order to do so it uses c++ idioms that are not yet widely supported Chris@16: // by current compiler releases. The library is designed to degrade gracefully Chris@16: // in the face of compiler deficiencies. In general compiler Chris@16: // deficiencies result in less strict error checking and more obscure Chris@16: // error messages, functionality is not affected. Chris@16: // Chris@16: // For full operation compiler support for "Substitution Failure Is Not An Error" Chris@16: // (aka. enable_if) and boost::is_convertible is required. Chris@16: // Chris@16: // The following problems occur if support is lacking. Chris@16: // Chris@16: // Pseudo code Chris@16: // Chris@16: // --------------- Chris@16: // AdaptorA a1; Chris@16: // AdaptorA a2; Chris@16: // Chris@16: // // This will result in a no such overload error in full operation Chris@16: // // If enable_if or is_convertible is not supported Chris@16: // // The instantiation will fail with an error hopefully indicating that Chris@16: // // there is no operator== for Iterator1, Iterator2 Chris@16: // // The same will happen if no enable_if is used to remove Chris@16: // // false overloads from the templated conversion constructor Chris@16: // // of AdaptorA. Chris@16: // Chris@16: // a1 == a2; Chris@16: // ---------------- Chris@16: // Chris@16: // AdaptorA a; Chris@16: // AdaptorB b; Chris@16: // Chris@16: // // This will result in a no such overload error in full operation Chris@16: // // If enable_if is not supported the static assert used Chris@16: // // in the operator implementation will fail. Chris@16: // // This will accidently work if is_convertible is not supported. Chris@16: // Chris@16: // a == b; Chris@16: // ---------------- Chris@16: // Chris@16: Chris@16: # ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP Chris@16: # define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_() Chris@16: # else Chris@16: # define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible() Chris@16: # endif Chris@16: Chris@16: # define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \ Chris@16: BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \ Chris@16: { \ Chris@16: /* For those compilers that do not support enable_if */ \ Chris@16: BOOST_STATIC_ASSERT(( \ Chris@16: is_interoperable< Derived1, Derived2 >::value \ Chris@16: )); \ Chris@16: return_prefix iterator_core_access::base_op( \ Chris@16: *static_cast(&lhs) \ Chris@16: , *static_cast(&rhs) \ Chris@16: , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \ Chris@16: ); \ Chris@16: } Chris@16: Chris@16: # define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \ Chris@16: BOOST_ITERATOR_FACADE_INTEROP( \ Chris@16: op \ Chris@101: , boost::iterators::detail::always_bool2 \ Chris@16: , return_prefix \ Chris@16: , base_op \ Chris@16: ) Chris@16: Chris@16: BOOST_ITERATOR_FACADE_RELATION(==, return, equal) Chris@16: BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal) Chris@16: Chris@16: # undef BOOST_ITERATOR_FACADE_RELATION Chris@16: Chris@101: Chris@101: # define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(op, result_type, return_prefix, base_op) \ Chris@101: BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(inline, op, result_type) \ Chris@101: { \ Chris@101: /* For those compilers that do not support enable_if */ \ Chris@101: BOOST_STATIC_ASSERT(( \ Chris@101: is_interoperable< Derived1, Derived2 >::value && \ Chris@101: boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived1 >::type, random_access_traversal_tag >::value && \ Chris@101: boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived2 >::type, random_access_traversal_tag >::value \ Chris@101: )); \ Chris@101: return_prefix iterator_core_access::base_op( \ Chris@101: *static_cast(&lhs) \ Chris@101: , *static_cast(&rhs) \ Chris@101: , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \ Chris@101: ); \ Chris@101: } Chris@101: Chris@101: # define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op, return_prefix, base_op) \ Chris@101: BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( \ Chris@101: op \ Chris@101: , boost::iterators::detail::always_bool2 \ Chris@101: , return_prefix \ Chris@101: , base_op \ Chris@101: ) Chris@101: Chris@101: BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<, return 0 >, distance_from) Chris@101: BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>, return 0 <, distance_from) Chris@101: BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=, return 0 >=, distance_from) Chris@101: BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=, return 0 <=, distance_from) Chris@101: Chris@101: # undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION Chris@101: Chris@16: // operator- requires an additional part in the static assertion Chris@101: BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( Chris@16: - Chris@101: , boost::iterators::detail::choose_difference_type Chris@16: , return Chris@16: , distance_from Chris@16: ) Chris@101: Chris@16: # undef BOOST_ITERATOR_FACADE_INTEROP Chris@101: # undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS Chris@16: Chris@16: # define BOOST_ITERATOR_FACADE_PLUS(args) \ Chris@16: BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \ Chris@16: { \ Chris@16: Derived tmp(static_cast(i)); \ Chris@16: return tmp += n; \ Chris@16: } Chris@16: Chris@101: BOOST_ITERATOR_FACADE_PLUS(( Chris@101: iterator_facade const& i Chris@101: , typename Derived::difference_type n Chris@101: )) Chris@16: Chris@101: BOOST_ITERATOR_FACADE_PLUS(( Chris@101: typename Derived::difference_type n Chris@16: , iterator_facade const& i Chris@101: )) Chris@101: Chris@16: # undef BOOST_ITERATOR_FACADE_PLUS Chris@16: # undef BOOST_ITERATOR_FACADE_PLUS_HEAD Chris@16: Chris@101: # undef BOOST_ITERATOR_FACADE_INTEROP_HEAD Chris@101: # undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD Chris@101: # undef BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL Chris@101: Chris@101: } // namespace iterators Chris@101: Chris@101: using iterators::iterator_core_access; Chris@101: using iterators::iterator_facade; Chris@101: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_ITERATOR_FACADE_23022003THW_HPP