diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 1030eb9..879beb3 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -27,6 +28,8 @@ #include #include #include +#include +#include #include // this goes last @@ -216,6 +219,23 @@ namespace boost return *iter; } + struct choose_difference_type + { + template + struct apply + : mpl::apply_if< + is_convertible +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + , typename I1::difference_type + , typename I2::difference_type +# else + , iterator_difference + , iterator_difference +# endif + > + {}; + + }; } // namespace detail @@ -226,7 +246,8 @@ namespace boost , class Derived2, class V2, class TC2, class R2, class D2 \ > \ prefix typename detail::enable_if_interoperable< \ - Derived1, Derived2, result_type \ + Derived1, Derived2 \ + , typename mpl::apply2::type \ >::type \ operator op( \ iterator_facade const& lhs \ @@ -256,8 +277,8 @@ namespace boost template friend class iterator_facade; -# define BOOST_ITERATOR_FACADE_RELATION(op) \ - BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool); +# define BOOST_ITERATOR_FACADE_RELATION(op) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, mpl::always); BOOST_ITERATOR_FACADE_RELATION(==) BOOST_ITERATOR_FACADE_RELATION(!=) @@ -269,7 +290,7 @@ namespace boost # undef BOOST_ITERATOR_FACADE_RELATION BOOST_ITERATOR_FACADE_INTEROP_HEAD( - friend, -, typename Derived1::difference_type) + friend, -, detail::choose_difference_type) ; BOOST_ITERATOR_FACADE_PLUS_HEAD( @@ -307,11 +328,17 @@ namespace boost } template - static bool equal(Facade1 const& f1, Facade2 const& f2) + static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_) { return f1.equal(f2); } + template + static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_) + { + return f2.equal(f1); + } + template static void advance(Facade& f, typename Facade::difference_type n) { @@ -319,10 +346,17 @@ namespace boost } template - static typename Facade1::difference_type distance_to( - Facade1 const& f1, Facade2 const& f2) + static typename Facade1::difference_type minus( + Facade1 const& f1, Facade2 const& f2, mpl::true_) { - return f1.distance_to(f2); + return -f1.distance_to(f2); + } + + template + static typename Facade2::difference_type minus( + Facade1 const& f1, Facade2 const& f2, mpl::false_) + { + return f2.distance_to(f1); } private: @@ -531,23 +565,24 @@ namespace boost // ---------------- // -# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, condition, return_prefix, base_op) \ - BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \ - { \ - /* For those compilers that do not support enable_if */ \ - BOOST_STATIC_ASSERT(( \ - is_interoperable< Derived1, Derived2 >::value \ - && condition \ - )); \ - return_prefix iterator_core_access::base_op( \ - static_cast(rhs), static_cast(lhs)); \ +# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \ + { \ + /* For those compilers that do not support enable_if */ \ + BOOST_STATIC_ASSERT(( \ + is_interoperable< Derived1, Derived2 >::value \ + )); \ + return_prefix iterator_core_access::base_op( \ + static_cast(lhs) \ + , static_cast(rhs) \ + , is_convertible() \ + ); \ } # define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \ BOOST_ITERATOR_FACADE_INTEROP( \ op \ - , bool \ - , true \ + , mpl::always \ , return_prefix \ , base_op \ ) @@ -555,22 +590,19 @@ namespace boost BOOST_ITERATOR_FACADE_RELATION(==, return, equal) BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal) - BOOST_ITERATOR_FACADE_RELATION(<, return 0 >, distance_to) - BOOST_ITERATOR_FACADE_RELATION(>, return 0 <, distance_to) - BOOST_ITERATOR_FACADE_RELATION(<=, return 0 >=, distance_to) - BOOST_ITERATOR_FACADE_RELATION(>=, return 0 <=, distance_to) + BOOST_ITERATOR_FACADE_RELATION(<, return 0 >, minus) + BOOST_ITERATOR_FACADE_RELATION(>, return 0 <, minus) + BOOST_ITERATOR_FACADE_RELATION(<=, return 0 >=, minus) + BOOST_ITERATOR_FACADE_RELATION(>=, return 0 <=, minus) # undef BOOST_ITERATOR_FACADE_RELATION // operator- requires an additional part in the static assertion BOOST_ITERATOR_FACADE_INTEROP( - - , typename Derived1::difference_type - , (is_same< - BOOST_DEDUCED_TYPENAME Derived1::difference_type - , BOOST_DEDUCED_TYPENAME Derived2::difference_type - >::value) + , detail::choose_difference_type , return - , distance_to ) + , minus + ) # undef BOOST_ITERATOR_FACADE_INTEROP # undef BOOST_ITERATOR_FACADE_INTEROP_HEAD diff --git a/test/Jamfile b/test/Jamfile index b5629e4..32f34e5 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -42,6 +42,7 @@ test-suite iterator [ run filter_iterator_test.cpp ] [ run reverse_iterator_test.cpp ] [ run counting_iterator_test.cpp ] + [ run interoperable.cpp ] [ run permutation_iterator_test.cpp : : : # on ] diff --git a/test/interoperable.cpp b/test/interoperable.cpp new file mode 100755 index 0000000..c228b9c --- /dev/null +++ b/test/interoperable.cpp @@ -0,0 +1,59 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +struct mutable_it : boost::iterator_adaptor +{ + typedef boost::iterator_adaptor super_t; + + mutable_it(); + explicit mutable_it(int* p) : super_t(p) {} + + bool equal(mutable_it const& rhs) const + { + return this->base() == rhs.base(); + } +}; + +struct constant_it : boost::iterator_adaptor +{ + typedef boost::iterator_adaptor super_t; + + constant_it(); + explicit constant_it(int* p) : super_t(p) {} + constant_it(mutable_it const& x) : super_t(x.base()) {} + + bool equal(constant_it const& rhs) const + { + return this->base() == rhs.base(); + } +}; + +int main() +{ + int data[] = { 49, 77 }; + + mutable_it i(data); + constant_it j(data + 1); + assert(i < j); + assert(j > i); + assert(i <= j); + assert(j >= i); + assert(j - i == 1); + assert(i - j == -1); + + constant_it k = i; + + assert(!(i < k)); + assert(!(k > i)); + assert(i <= k); + assert(k >= i); + assert(k - i == 0); + assert(i - k == 0); + + return 0; +}