mirror of
https://github.com/boostorg/iterator.git
synced 2025-07-18 07:02:21 +02:00
Added thomas' interoperability idea
[SVN r21762]
This commit is contained in:
@ -13,6 +13,7 @@
|
||||
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/interoperable.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
|
||||
#include <boost/iterator/detail/facade_iterator_category.hpp>
|
||||
#include <boost/iterator/detail/enable_if.hpp>
|
||||
@ -27,6 +28,8 @@
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/always.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
|
||||
#include <boost/iterator/detail/config_def.hpp> // this goes last
|
||||
|
||||
@ -216,6 +219,23 @@ namespace boost
|
||||
return *iter;
|
||||
}
|
||||
|
||||
struct choose_difference_type
|
||||
{
|
||||
template <class I1, class I2>
|
||||
struct apply
|
||||
: mpl::apply_if<
|
||||
is_convertible<I2,I1>
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
, typename I1::difference_type
|
||||
, typename I2::difference_type
|
||||
# else
|
||||
, iterator_difference<I1>
|
||||
, iterator_difference<I2>
|
||||
# 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<result_type,Derived1,Derived2>::type \
|
||||
>::type \
|
||||
operator op( \
|
||||
iterator_facade<Derived1, V1, TC1, R1, D1> const& lhs \
|
||||
@ -257,7 +278,7 @@ namespace boost
|
||||
template <class I, class V, class TC, class R, class D> friend class iterator_facade;
|
||||
|
||||
# define BOOST_ITERATOR_FACADE_RELATION(op) \
|
||||
BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool);
|
||||
BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, mpl::always<bool>);
|
||||
|
||||
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 <class Facade1, class Facade2>
|
||||
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 <class Facade1, class Facade2>
|
||||
static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_)
|
||||
{
|
||||
return f2.equal(f1);
|
||||
}
|
||||
|
||||
template <class Facade>
|
||||
static void advance(Facade& f, typename Facade::difference_type n)
|
||||
{
|
||||
@ -319,10 +346,17 @@ namespace boost
|
||||
}
|
||||
|
||||
template <class Facade1, class Facade2>
|
||||
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 <class Facade1, class Facade2>
|
||||
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) \
|
||||
# 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 \
|
||||
&& condition \
|
||||
)); \
|
||||
return_prefix iterator_core_access::base_op( \
|
||||
static_cast<Derived2 const&>(rhs), static_cast<Derived1 const&>(lhs)); \
|
||||
static_cast<Derived1 const&>(lhs) \
|
||||
, static_cast<Derived2 const&>(rhs) \
|
||||
, is_convertible<Derived2,Derived1>() \
|
||||
); \
|
||||
}
|
||||
|
||||
# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
|
||||
BOOST_ITERATOR_FACADE_INTEROP( \
|
||||
op \
|
||||
, bool \
|
||||
, true \
|
||||
, mpl::always<bool> \
|
||||
, 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
|
||||
|
||||
|
@ -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 : : : # <stlport-iostream>on
|
||||
]
|
||||
|
||||
|
59
test/interoperable.cpp
Executable file
59
test/interoperable.cpp
Executable file
@ -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 <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/pending/iterator_tests.hpp>
|
||||
#include <cassert>
|
||||
|
||||
struct mutable_it : boost::iterator_adaptor<mutable_it,int*>
|
||||
{
|
||||
typedef boost::iterator_adaptor<mutable_it,int*> 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<constant_it,int const*>
|
||||
{
|
||||
typedef boost::iterator_adaptor<constant_it,int const*> 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;
|
||||
}
|
Reference in New Issue
Block a user