From 36988fcf981c99b297383c8fd7acc423bd7652d4 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 29 Jun 2014 15:42:47 +0400 Subject: [PATCH 1/3] Removed executable flags from headers. --- include/boost/iterator/detail/any_conversion_eater.hpp | 0 include/boost/iterator/is_lvalue_iterator.hpp | 0 include/boost/iterator/is_readable_iterator.hpp | 0 include/boost/pointee.hpp | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 include/boost/iterator/detail/any_conversion_eater.hpp mode change 100755 => 100644 include/boost/iterator/is_lvalue_iterator.hpp mode change 100755 => 100644 include/boost/iterator/is_readable_iterator.hpp mode change 100755 => 100644 include/boost/pointee.hpp diff --git a/include/boost/iterator/detail/any_conversion_eater.hpp b/include/boost/iterator/detail/any_conversion_eater.hpp old mode 100755 new mode 100644 diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp old mode 100755 new mode 100644 diff --git a/include/boost/iterator/is_readable_iterator.hpp b/include/boost/iterator/is_readable_iterator.hpp old mode 100755 new mode 100644 diff --git a/include/boost/pointee.hpp b/include/boost/pointee.hpp old mode 100755 new mode 100644 From fd94cc7d780d1bf74a64d2521fffd9184e277afb Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 29 Jun 2014 15:49:05 +0400 Subject: [PATCH 2/3] Removed executable flags from docs, tests and examples. --- doc/BidirectionalTraversal.rst | 0 doc/ForwardTraversal.rst | 0 doc/GNUmakefile | 0 doc/IncrementableIterator.rst | 0 doc/LvalueIterator.rst | 0 doc/ReadableIterator.rst | 0 doc/SinglePassIterator.rst | 0 doc/SwappableIterator.rst | 0 doc/WritableIterator.rst | 0 doc/counting_iterator.pdf | Bin doc/docutils.sty | 0 doc/facade-and-adaptor.pdf | Bin doc/facade_iterator_category.rst | 0 doc/filter_iterator.pdf | Bin doc/function_output_iterator.pdf | Bin doc/indirect_iterator.pdf | Bin doc/indirect_reference_ref.rst | 0 doc/interoperability-revisited.rst | 0 doc/iterator_adaptor.pdf | Bin doc/iterator_adaptor_tutorial.rst | 0 doc/iterator_archetypes.html | 0 doc/iterator_archetypes.pdf | Bin doc/iterator_archetypes.rst | 0 doc/iterator_concepts.pdf | Bin doc/iterator_concepts.rst | 0 doc/iterator_facade.pdf | Bin doc/iterator_facade_tutorial.rst | 0 doc/iterator_traits.html | 0 doc/iterator_traits.pdf | Bin doc/iterator_traits.rst | 0 doc/make_counting_iterator.rst | 0 doc/make_filter_iterator.rst | 0 doc/make_transform_iterator.rst | 0 doc/make_zip_iterator.rst | 0 doc/new-iter-concepts.pdf | Bin doc/permutation_iterator.pdf | Bin doc/pointee.html | 0 doc/pointee.pdf | Bin doc/pointee.rst | 0 doc/pointee_ref.rst | 0 doc/reverse_iterator.pdf | Bin doc/transform_iterator.pdf | Bin doc/transform_iterator_eg.rst | 0 doc/zip_iterator.html | 0 doc/zip_iterator.pdf | Bin doc/zip_iterator.rst | 0 doc/zip_iterator_abstract.rst | 0 doc/zip_iterator_eg.rst | 0 doc/zip_iterator_ref.rst | 0 example/node.hpp | 0 example/node_iterator1.cpp | 0 example/node_iterator1.hpp | 0 example/node_iterator2.cpp | 0 example/node_iterator2.hpp | 0 example/node_iterator3.cpp | 0 example/node_iterator3.hpp | 0 index.html | 0 test/constant_iter_arrow.cpp | 0 test/constant_iter_arrow_fail.cpp | 0 test/interoperable.cpp | 0 test/iter_archetype_default_ctor.cpp | 0 61 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 doc/BidirectionalTraversal.rst mode change 100755 => 100644 doc/ForwardTraversal.rst mode change 100755 => 100644 doc/GNUmakefile mode change 100755 => 100644 doc/IncrementableIterator.rst mode change 100755 => 100644 doc/LvalueIterator.rst mode change 100755 => 100644 doc/ReadableIterator.rst mode change 100755 => 100644 doc/SinglePassIterator.rst mode change 100755 => 100644 doc/SwappableIterator.rst mode change 100755 => 100644 doc/WritableIterator.rst mode change 100755 => 100644 doc/counting_iterator.pdf mode change 100755 => 100644 doc/docutils.sty mode change 100755 => 100644 doc/facade-and-adaptor.pdf mode change 100755 => 100644 doc/facade_iterator_category.rst mode change 100755 => 100644 doc/filter_iterator.pdf mode change 100755 => 100644 doc/function_output_iterator.pdf mode change 100755 => 100644 doc/indirect_iterator.pdf mode change 100755 => 100644 doc/indirect_reference_ref.rst mode change 100755 => 100644 doc/interoperability-revisited.rst mode change 100755 => 100644 doc/iterator_adaptor.pdf mode change 100755 => 100644 doc/iterator_adaptor_tutorial.rst mode change 100755 => 100644 doc/iterator_archetypes.html mode change 100755 => 100644 doc/iterator_archetypes.pdf mode change 100755 => 100644 doc/iterator_archetypes.rst mode change 100755 => 100644 doc/iterator_concepts.pdf mode change 100755 => 100644 doc/iterator_concepts.rst mode change 100755 => 100644 doc/iterator_facade.pdf mode change 100755 => 100644 doc/iterator_facade_tutorial.rst mode change 100755 => 100644 doc/iterator_traits.html mode change 100755 => 100644 doc/iterator_traits.pdf mode change 100755 => 100644 doc/iterator_traits.rst mode change 100755 => 100644 doc/make_counting_iterator.rst mode change 100755 => 100644 doc/make_filter_iterator.rst mode change 100755 => 100644 doc/make_transform_iterator.rst mode change 100755 => 100644 doc/make_zip_iterator.rst mode change 100755 => 100644 doc/new-iter-concepts.pdf mode change 100755 => 100644 doc/permutation_iterator.pdf mode change 100755 => 100644 doc/pointee.html mode change 100755 => 100644 doc/pointee.pdf mode change 100755 => 100644 doc/pointee.rst mode change 100755 => 100644 doc/pointee_ref.rst mode change 100755 => 100644 doc/reverse_iterator.pdf mode change 100755 => 100644 doc/transform_iterator.pdf mode change 100755 => 100644 doc/transform_iterator_eg.rst mode change 100755 => 100644 doc/zip_iterator.html mode change 100755 => 100644 doc/zip_iterator.pdf mode change 100755 => 100644 doc/zip_iterator.rst mode change 100755 => 100644 doc/zip_iterator_abstract.rst mode change 100755 => 100644 doc/zip_iterator_eg.rst mode change 100755 => 100644 doc/zip_iterator_ref.rst mode change 100755 => 100644 example/node.hpp mode change 100755 => 100644 example/node_iterator1.cpp mode change 100755 => 100644 example/node_iterator1.hpp mode change 100755 => 100644 example/node_iterator2.cpp mode change 100755 => 100644 example/node_iterator2.hpp mode change 100755 => 100644 example/node_iterator3.cpp mode change 100755 => 100644 example/node_iterator3.hpp mode change 100755 => 100644 index.html mode change 100755 => 100644 test/constant_iter_arrow.cpp mode change 100755 => 100644 test/constant_iter_arrow_fail.cpp mode change 100755 => 100644 test/interoperable.cpp mode change 100755 => 100644 test/iter_archetype_default_ctor.cpp diff --git a/doc/BidirectionalTraversal.rst b/doc/BidirectionalTraversal.rst old mode 100755 new mode 100644 diff --git a/doc/ForwardTraversal.rst b/doc/ForwardTraversal.rst old mode 100755 new mode 100644 diff --git a/doc/GNUmakefile b/doc/GNUmakefile old mode 100755 new mode 100644 diff --git a/doc/IncrementableIterator.rst b/doc/IncrementableIterator.rst old mode 100755 new mode 100644 diff --git a/doc/LvalueIterator.rst b/doc/LvalueIterator.rst old mode 100755 new mode 100644 diff --git a/doc/ReadableIterator.rst b/doc/ReadableIterator.rst old mode 100755 new mode 100644 diff --git a/doc/SinglePassIterator.rst b/doc/SinglePassIterator.rst old mode 100755 new mode 100644 diff --git a/doc/SwappableIterator.rst b/doc/SwappableIterator.rst old mode 100755 new mode 100644 diff --git a/doc/WritableIterator.rst b/doc/WritableIterator.rst old mode 100755 new mode 100644 diff --git a/doc/counting_iterator.pdf b/doc/counting_iterator.pdf old mode 100755 new mode 100644 diff --git a/doc/docutils.sty b/doc/docutils.sty old mode 100755 new mode 100644 diff --git a/doc/facade-and-adaptor.pdf b/doc/facade-and-adaptor.pdf old mode 100755 new mode 100644 diff --git a/doc/facade_iterator_category.rst b/doc/facade_iterator_category.rst old mode 100755 new mode 100644 diff --git a/doc/filter_iterator.pdf b/doc/filter_iterator.pdf old mode 100755 new mode 100644 diff --git a/doc/function_output_iterator.pdf b/doc/function_output_iterator.pdf old mode 100755 new mode 100644 diff --git a/doc/indirect_iterator.pdf b/doc/indirect_iterator.pdf old mode 100755 new mode 100644 diff --git a/doc/indirect_reference_ref.rst b/doc/indirect_reference_ref.rst old mode 100755 new mode 100644 diff --git a/doc/interoperability-revisited.rst b/doc/interoperability-revisited.rst old mode 100755 new mode 100644 diff --git a/doc/iterator_adaptor.pdf b/doc/iterator_adaptor.pdf old mode 100755 new mode 100644 diff --git a/doc/iterator_adaptor_tutorial.rst b/doc/iterator_adaptor_tutorial.rst old mode 100755 new mode 100644 diff --git a/doc/iterator_archetypes.html b/doc/iterator_archetypes.html old mode 100755 new mode 100644 diff --git a/doc/iterator_archetypes.pdf b/doc/iterator_archetypes.pdf old mode 100755 new mode 100644 diff --git a/doc/iterator_archetypes.rst b/doc/iterator_archetypes.rst old mode 100755 new mode 100644 diff --git a/doc/iterator_concepts.pdf b/doc/iterator_concepts.pdf old mode 100755 new mode 100644 diff --git a/doc/iterator_concepts.rst b/doc/iterator_concepts.rst old mode 100755 new mode 100644 diff --git a/doc/iterator_facade.pdf b/doc/iterator_facade.pdf old mode 100755 new mode 100644 diff --git a/doc/iterator_facade_tutorial.rst b/doc/iterator_facade_tutorial.rst old mode 100755 new mode 100644 diff --git a/doc/iterator_traits.html b/doc/iterator_traits.html old mode 100755 new mode 100644 diff --git a/doc/iterator_traits.pdf b/doc/iterator_traits.pdf old mode 100755 new mode 100644 diff --git a/doc/iterator_traits.rst b/doc/iterator_traits.rst old mode 100755 new mode 100644 diff --git a/doc/make_counting_iterator.rst b/doc/make_counting_iterator.rst old mode 100755 new mode 100644 diff --git a/doc/make_filter_iterator.rst b/doc/make_filter_iterator.rst old mode 100755 new mode 100644 diff --git a/doc/make_transform_iterator.rst b/doc/make_transform_iterator.rst old mode 100755 new mode 100644 diff --git a/doc/make_zip_iterator.rst b/doc/make_zip_iterator.rst old mode 100755 new mode 100644 diff --git a/doc/new-iter-concepts.pdf b/doc/new-iter-concepts.pdf old mode 100755 new mode 100644 diff --git a/doc/permutation_iterator.pdf b/doc/permutation_iterator.pdf old mode 100755 new mode 100644 diff --git a/doc/pointee.html b/doc/pointee.html old mode 100755 new mode 100644 diff --git a/doc/pointee.pdf b/doc/pointee.pdf old mode 100755 new mode 100644 diff --git a/doc/pointee.rst b/doc/pointee.rst old mode 100755 new mode 100644 diff --git a/doc/pointee_ref.rst b/doc/pointee_ref.rst old mode 100755 new mode 100644 diff --git a/doc/reverse_iterator.pdf b/doc/reverse_iterator.pdf old mode 100755 new mode 100644 diff --git a/doc/transform_iterator.pdf b/doc/transform_iterator.pdf old mode 100755 new mode 100644 diff --git a/doc/transform_iterator_eg.rst b/doc/transform_iterator_eg.rst old mode 100755 new mode 100644 diff --git a/doc/zip_iterator.html b/doc/zip_iterator.html old mode 100755 new mode 100644 diff --git a/doc/zip_iterator.pdf b/doc/zip_iterator.pdf old mode 100755 new mode 100644 diff --git a/doc/zip_iterator.rst b/doc/zip_iterator.rst old mode 100755 new mode 100644 diff --git a/doc/zip_iterator_abstract.rst b/doc/zip_iterator_abstract.rst old mode 100755 new mode 100644 diff --git a/doc/zip_iterator_eg.rst b/doc/zip_iterator_eg.rst old mode 100755 new mode 100644 diff --git a/doc/zip_iterator_ref.rst b/doc/zip_iterator_ref.rst old mode 100755 new mode 100644 diff --git a/example/node.hpp b/example/node.hpp old mode 100755 new mode 100644 diff --git a/example/node_iterator1.cpp b/example/node_iterator1.cpp old mode 100755 new mode 100644 diff --git a/example/node_iterator1.hpp b/example/node_iterator1.hpp old mode 100755 new mode 100644 diff --git a/example/node_iterator2.cpp b/example/node_iterator2.cpp old mode 100755 new mode 100644 diff --git a/example/node_iterator2.hpp b/example/node_iterator2.hpp old mode 100755 new mode 100644 diff --git a/example/node_iterator3.cpp b/example/node_iterator3.cpp old mode 100755 new mode 100644 diff --git a/example/node_iterator3.hpp b/example/node_iterator3.hpp old mode 100755 new mode 100644 diff --git a/index.html b/index.html old mode 100755 new mode 100644 diff --git a/test/constant_iter_arrow.cpp b/test/constant_iter_arrow.cpp old mode 100755 new mode 100644 diff --git a/test/constant_iter_arrow_fail.cpp b/test/constant_iter_arrow_fail.cpp old mode 100755 new mode 100644 diff --git a/test/interoperable.cpp b/test/interoperable.cpp old mode 100755 new mode 100644 diff --git a/test/iter_archetype_default_ctor.cpp b/test/iter_archetype_default_ctor.cpp old mode 100755 new mode 100644 From 7fa65a4278aad66bffbdf56635a35a2442745bce Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 30 Jun 2014 00:05:38 +0400 Subject: [PATCH 3/3] Made iterator operators conditionally defined depending on its category. This makes iterators defined using iterator_facade more friendly to type inspection and fixes its use with next()/prior() since commit https://github.com/boostorg/utility/commit/651a869d4f9479dd3dfdd0293305a60b8c8d0e1c. The arithmetic, indexing and relational operators are only defined if the iterator category or traversal permits that. Note that the implementation requires partial template specialization support now. --- include/boost/iterator/iterator_facade.hpp | 440 ++++++++++++++------- 1 file changed, 292 insertions(+), 148 deletions(-) diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index d08b2ba..5ac1cb6 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -7,9 +7,11 @@ #ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP #define BOOST_ITERATOR_FACADE_23022003THW_HPP +#include #include #include #include +#include #include #include @@ -56,6 +58,12 @@ namespace boost }; }; + // The type trait checks if the category or traversal is at least as advanced as the specified required traversal + template< typename CategoryOrTraversal, typename Required > + struct is_traversal_at_least : + public boost::is_convertible< typename iterator_category_to_traversal< CategoryOrTraversal >::type, Required > + {}; + // // enable if for use in operator implementation. // @@ -64,13 +72,29 @@ namespace boost , class Facade2 , class Return > - struct enable_if_interoperable - : ::boost::iterators::enable_if< - mpl::or_< - is_convertible - , is_convertible - > - , Return + struct enable_if_interoperable : + public boost::iterators::enable_if< + is_interoperable< Facade1, Facade2 > + , Return + > + {}; + + // + // enable if for use in implementation of operators specific for random access traversal. + // + template < + class Facade1 + , class Facade2 + , class Return + > + struct enable_if_interoperable_and_random_access_traversal : + public boost::iterators::enable_if< + mpl::and_< + is_interoperable< Facade1, Facade2 > + , is_traversal_at_least< typename iterator_category< Facade1 >::type, random_access_traversal_tag > + , is_traversal_at_least< typename iterator_category< Facade2 >::type, random_access_traversal_tag > + > + , Return > {}; @@ -81,7 +105,7 @@ namespace boost template < class ValueParam , class CategoryOrTraversal - , class Reference + , class Reference , class Difference > struct iterator_facade_types @@ -89,16 +113,16 @@ namespace boost typedef typename facade_iterator_category< CategoryOrTraversal, ValueParam, Reference >::type iterator_category; - + typedef typename remove_const::type value_type; - + // Not the real associated pointer type typedef typename mpl::eval_if< boost::detail::iterator_writability_disabled , add_pointer , add_pointer >::type pointer; - + # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ @@ -144,7 +168,7 @@ namespace boost private: mutable value_type stored_value; }; - + // // In general, we can't determine that such an iterator isn't // writable -- we also need to store a copy of the old iterator so @@ -196,7 +220,7 @@ namespace boost { return stored_iterator; } - + private: mutable value_type stored_value; Iterator stored_iterator; @@ -208,7 +232,7 @@ namespace boost struct is_non_proxy_reference_impl { static Reference r; - + template static typename mpl::if_< is_convertible< @@ -218,17 +242,17 @@ namespace boost , char[1] , char[2] >::type& helper(R const&); - + BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1); }; - + template struct is_non_proxy_reference : mpl::bool_< is_non_proxy_reference_impl::value > {}; -# else +# else template struct is_non_proxy_reference : is_convertible< @@ -237,8 +261,8 @@ namespace boost , Value const volatile* > {}; -# endif - +# endif + // A metafunction to choose the result type of postfix ++ // // Because the C++98 input iterator requirements say that *r++ has @@ -260,7 +284,7 @@ namespace boost mpl::and_< // A proxy is only needed for readable iterators is_convertible - + // No multipass iterator can have values that disappear // before positions can be re-visited , mpl::not_< @@ -356,7 +380,7 @@ namespace boost > > {}; - + template struct operator_brackets_result { @@ -392,16 +416,28 @@ namespace boost , iterator_difference , iterator_difference > -# endif +# endif {}; }; + + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference + , class Difference + , bool IsBidirectionalTraversal + , bool IsRandomAccessTraversal + > + class iterator_facade_base; + } // namespace detail // Macros which describe the declarations of binary operators # ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY -# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \ template < \ class Derived1, class V1, class TC1, class Reference1, class Difference1 \ , class Derived2, class V2, class TC2, class Reference2, class Difference2 \ @@ -410,24 +446,33 @@ namespace boost operator op( \ iterator_facade const& lhs \ , iterator_facade const& rhs) -# else -# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ +# else +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \ template < \ class Derived1, class V1, class TC1, class Reference1, class Difference1 \ , class Derived2, class V2, class TC2, class Reference2, class Difference2 \ > \ - prefix typename boost::detail::enable_if_interoperable< \ + prefix typename enabler< \ Derived1, Derived2 \ , typename mpl::apply2::type \ >::type \ operator op( \ iterator_facade const& lhs \ , iterator_facade const& rhs) -# endif +# endif + +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::detail::enable_if_interoperable) + +# define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(prefix, op, result_type) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::detail::enable_if_interoperable_and_random_access_traversal) # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ template \ - prefix Derived operator+ args + prefix typename boost::iterators::enable_if< \ + boost::detail::is_traversal_at_least< TC, boost::random_access_traversal_tag >, \ + Derived \ + >::type operator+ args // // Helper class for granting access to the iterator core interface. @@ -440,13 +485,15 @@ namespace boost // class iterator_core_access { -# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) +# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. public: # else - + template friend class iterator_facade; + template + friend class detail::iterator_facade_base; # define BOOST_ITERATOR_FACADE_RELATION(op) \ BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::detail::always_bool2); @@ -454,27 +501,33 @@ namespace boost BOOST_ITERATOR_FACADE_RELATION(==) BOOST_ITERATOR_FACADE_RELATION(!=) - BOOST_ITERATOR_FACADE_RELATION(<) - BOOST_ITERATOR_FACADE_RELATION(>) - BOOST_ITERATOR_FACADE_RELATION(<=) - BOOST_ITERATOR_FACADE_RELATION(>=) # undef BOOST_ITERATOR_FACADE_RELATION - BOOST_ITERATOR_FACADE_INTEROP_HEAD( +# define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op) \ + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(friend,op, boost::detail::always_bool2); + + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=) + +# undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION + + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD( friend, -, boost::detail::choose_difference_type) ; BOOST_ITERATOR_FACADE_PLUS_HEAD( friend inline - , (iterator_facade const& - , typename Derived::difference_type) + , (iterator_facade const& + , typename Derived::difference_type) ) ; BOOST_ITERATOR_FACADE_PLUS_HEAD( friend inline , (typename Derived::difference_type - , iterator_facade const&) + , iterator_facade const&) ) ; @@ -545,11 +598,156 @@ namespace boost return *static_cast(&facade); } - private: // objects of this class are useless - iterator_core_access(); //undefined + BOOST_DELETED_FUNCTION(iterator_core_access()) }; + namespace detail { + + // Implementation for forward traversal iterators + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference + , class Difference + > + class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false > +# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE + : public boost::detail::iterator_facade_types< + Value, CategoryOrTraversal, Reference, Difference + >::base +# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE +# endif + { + private: + typedef boost::detail::iterator_facade_types< + Value, CategoryOrTraversal, Reference, Difference + > associated_types; + + typedef boost::detail::operator_arrow_dispatch< + Reference + , typename associated_types::pointer + > operator_arrow_dispatch_; + + public: + typedef typename associated_types::value_type value_type; + typedef Reference reference; + typedef Difference difference_type; + + typedef typename operator_arrow_dispatch_::result_type pointer; + + typedef typename associated_types::iterator_category iterator_category; + + public: + reference operator*() const + { + return iterator_core_access::dereference(this->derived()); + } + + pointer operator->() const + { + return operator_arrow_dispatch_::apply(*this->derived()); + } + + Derived& operator++() + { + iterator_core_access::increment(this->derived()); + return this->derived(); + } + + protected: + // + // Curiously Recurring Template interface. + // + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } + }; + + // Implementation for bidirectional traversal iterators + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference + , class Difference + > + class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > : + public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false > + { + public: + Derived& operator--() + { + iterator_core_access::decrement(this->derived()); + return this->derived(); + } + + Derived operator--(int) + { + Derived tmp(this->derived()); + --*this; + return tmp; + } + }; + + // Implementation for random access traversal iterators + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference + , class Difference + > + class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, true > : + public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > + { + private: + typedef iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > base_type; + + public: + typedef typename base_type::reference reference; + typedef typename base_type::difference_type difference_type; + + public: + typename boost::detail::operator_brackets_result::type + operator[](difference_type n) const + { + typedef boost::detail::use_operator_brackets_proxy use_proxy; + + return boost::detail::make_operator_brackets_result( + this->derived() + n + , use_proxy() + ); + } + + Derived& operator+=(difference_type n) + { + iterator_core_access::advance(this->derived(), n); + return this->derived(); + } + + Derived& operator-=(difference_type n) + { + iterator_core_access::advance(this->derived(), -n); + return this->derived(); + } + + Derived operator-(difference_type x) const + { + Derived result(this->derived()); + return result -= x; + } + }; + + } // namespace detail + // // iterator_facade - use as a public base class for defining new // standard-conforming iterators. @@ -561,108 +759,20 @@ namespace boost , class Reference = Value& , class Difference = std::ptrdiff_t > - class iterator_facade -# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE - : public boost::detail::iterator_facade_types< - Value, CategoryOrTraversal, Reference, Difference - >::base -# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE -# endif + class iterator_facade : + public detail::iterator_facade_base< + Derived, + Value, + CategoryOrTraversal, + Reference, + Difference, + detail::is_traversal_at_least< CategoryOrTraversal, bidirectional_traversal_tag >::value, + detail::is_traversal_at_least< CategoryOrTraversal, random_access_traversal_tag >::value + > { - private: - // - // Curiously Recurring Template interface. - // - Derived& derived() - { - return *static_cast(this); - } - - Derived const& derived() const - { - return *static_cast(this); - } - - typedef boost::detail::iterator_facade_types< - Value, CategoryOrTraversal, Reference, Difference - > associated_types; - - typedef boost::detail::operator_arrow_dispatch< - Reference - , typename associated_types::pointer - > operator_arrow_dispatch_; - - protected: + protected: // For use by derived classes typedef iterator_facade iterator_facade_; - - public: - - typedef typename associated_types::value_type value_type; - typedef Reference reference; - typedef Difference difference_type; - - typedef typename operator_arrow_dispatch_::result_type pointer; - - typedef typename associated_types::iterator_category iterator_category; - - reference operator*() const - { - return iterator_core_access::dereference(this->derived()); - } - - pointer operator->() const - { - return operator_arrow_dispatch_::apply(*this->derived()); - } - - typename boost::detail::operator_brackets_result::type - operator[](difference_type n) const - { - typedef boost::detail::use_operator_brackets_proxy use_proxy; - - return boost::detail::make_operator_brackets_result( - this->derived() + n - , use_proxy() - ); - } - - Derived& operator++() - { - iterator_core_access::increment(this->derived()); - return this->derived(); - } - - Derived& operator--() - { - iterator_core_access::decrement(this->derived()); - return this->derived(); - } - - Derived operator--(int) - { - Derived tmp(this->derived()); - --*this; - return tmp; - } - - Derived& operator+=(difference_type n) - { - iterator_core_access::advance(this->derived(), n); - return this->derived(); - } - - Derived& operator-=(difference_type n) - { - iterator_core_access::advance(this->derived(), -n); - return this->derived(); - } - - Derived operator-(difference_type x) const - { - Derived result(this->derived()); - return result -= x; - } }; template @@ -674,13 +784,13 @@ namespace boost { typename boost::detail::postfix_increment_result::type tmp(*static_cast(&i)); - + ++i; - + return tmp; } - + // // Comparison operator implementation. The library supplied operators // enables the user to provide fully interoperable constant/mutable @@ -779,21 +889,50 @@ namespace boost BOOST_ITERATOR_FACADE_RELATION(==, return, equal) BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal) - BOOST_ITERATOR_FACADE_RELATION(<, return 0 >, distance_from) - BOOST_ITERATOR_FACADE_RELATION(>, return 0 <, distance_from) - BOOST_ITERATOR_FACADE_RELATION(<=, return 0 >=, distance_from) - BOOST_ITERATOR_FACADE_RELATION(>=, return 0 <=, distance_from) # undef BOOST_ITERATOR_FACADE_RELATION + +# define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(op, result_type, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(inline, op, result_type) \ + { \ + /* For those compilers that do not support enable_if */ \ + BOOST_STATIC_ASSERT(( \ + is_interoperable< Derived1, Derived2 >::value && \ + boost::detail::is_traversal_at_least< typename iterator_category< Derived1 >::type, random_access_traversal_tag >::value && \ + boost::detail::is_traversal_at_least< typename iterator_category< Derived2 >::type, random_access_traversal_tag >::value \ + )); \ + return_prefix iterator_core_access::base_op( \ + *static_cast(&lhs) \ + , *static_cast(&rhs) \ + , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \ + ); \ + } + +# define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( \ + op \ + , boost::detail::always_bool2 \ + , return_prefix \ + , base_op \ + ) + + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<, return 0 >, distance_from) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>, return 0 <, distance_from) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=, return 0 >=, distance_from) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=, return 0 <=, distance_from) + +# undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION + // operator- requires an additional part in the static assertion - BOOST_ITERATOR_FACADE_INTEROP( + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( - , boost::detail::choose_difference_type , return , distance_from ) + # undef BOOST_ITERATOR_FACADE_INTEROP -# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD +# undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS # define BOOST_ITERATOR_FACADE_PLUS(args) \ BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \ @@ -811,9 +950,14 @@ BOOST_ITERATOR_FACADE_PLUS(( typename Derived::difference_type n , iterator_facade const& i )) + # undef BOOST_ITERATOR_FACADE_PLUS # undef BOOST_ITERATOR_FACADE_PLUS_HEAD +# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD +# undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD +# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL + } // namespace boost #include