From 0157a68e1f2925e0da715b31acc607c710159302 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 7 Nov 2002 05:09:44 +0000 Subject: [PATCH] Progress on indirect_iterator [SVN r670] --- include/boost/iterator/iterator_adaptors.hpp | 108 ++++++++++++-- test/Jamfile | 1 + test/indirect_iterator_test.cpp | 149 +++++++++++++++++++ 3 files changed, 249 insertions(+), 9 deletions(-) create mode 100644 test/indirect_iterator_test.cpp diff --git a/include/boost/iterator/iterator_adaptors.hpp b/include/boost/iterator/iterator_adaptors.hpp index a2bc8b6..7bf438e 100644 --- a/include/boost/iterator/iterator_adaptors.hpp +++ b/include/boost/iterator/iterator_adaptors.hpp @@ -46,28 +46,28 @@ template inline bool operator<(const iterator_comparisons& xb, const iterator_comparisons& yb) { - return xb.self().distance_to(yb.self()) < 0; + return xb.self().distance_to(yb.self()) > 0; } template inline bool operator>(const iterator_comparisons& xb, const iterator_comparisons& yb) { - return xb.self().distance_to(yb.self()) > 0; + return xb.self().distance_to(yb.self()) < 0; } template inline bool operator>=(const iterator_comparisons& xb, const iterator_comparisons& yb) { - return xb.self().distance_to(yb.self()) >= 0; + return xb.self().distance_to(yb.self()) <= 0; } template inline bool operator<=(const iterator_comparisons& xb, const iterator_comparisons& yb) { - return xb.self().distance_to(yb.self()) <= 0; + return xb.self().distance_to(yb.self()) >= 0; } @@ -97,9 +97,40 @@ typename Base1::difference_type operator-( const iterator_arith& i, const iterator_arith& j) { - return i.self().distance_to(i.self()); + return j.self().distance_to(i.self()); } +#if 0 +// Beginnings of a failed attempt to conditionally provide base() +// functions in iterator_adaptor. It may be that a public m_base +// member is the only way to avoid boilerplate! +struct unspecified {}; + +template +struct base_wrapper_impl +{ + template + struct apply : Super + { + apply() {} + apply(Base b) : m_base(b) {} + + Base base() const { return m_base; } + Base& base() { return m_base; } + private: + Base m_base; + }; +}; + +template <> +struct base_wrapper_impl +{ + template + struct apply : Super + { + }; +}; +#endif template > > > > -struct iterator_adaptor : B +struct iterator_adaptor : B { typedef V value_type; typedef R reference; @@ -117,7 +148,12 @@ struct iterator_adaptor : B reference operator*() const { return self().dereference(); } + + // Needs eventual help for input iterators + P operator->() const { return &self().dereference(); } + //operator->() const { return detail::operator_arrow(*this, iterator_category()); } + reference operator[](difference_type n) const { return *(*this + n); } Final& operator++() @@ -154,10 +190,10 @@ struct iterator_adaptor : B difference_type distance_to(const iterator_adaptor& y) const { - return self().base() - y.self().base();//? + return y.self().base() - self().base();//? } - - private: + + // Can't be private, or const/non-const interactions don't work using B::self; }; @@ -242,6 +278,60 @@ private: AdaptableUnaryFunction m_f; }; +// This macro definition is only temporary in this file +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +namespace detail +{ + template + struct traits_of_value_type + : detail::iterator_traits::value_type> + { + }; +} + +template ::value_type + , class Reference + = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< + Base>::reference + , class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits< + Base>::iterator_category + , class Pointer + = BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type< + Base>::pointer + > +struct indirect_iterator + : iterator_adaptor< + indirect_iterator + , Value, Reference, Pointer, Category + , typename detail::iterator_traits::difference_type + > +{ + Reference dereference() const { return **this->m_base; } + + indirect_iterator() {} + + indirect_iterator(Base iter) + : m_base(iter) {} + + template + indirect_iterator(const indirect_iterator& y) + : m_base(y.base()) + {} + + Base& base() { return m_base; } + Base const& base() const { return m_base; } + private: + Base m_base; +}; + } // namespace boost diff --git a/test/Jamfile b/test/Jamfile index f776325..1fc4e61 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -2,3 +2,4 @@ SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; include testing.jam ; run iterator_adaptor_cc.cpp ; run transform_iterator_test.cpp ; +run indirect_iterator_test.cpp ; \ No newline at end of file diff --git a/test/indirect_iterator_test.cpp b/test/indirect_iterator_test.cpp new file mode 100644 index 0000000..9fb1845 --- /dev/null +++ b/test/indirect_iterator_test.cpp @@ -0,0 +1,149 @@ +// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +// Revision History +// 08 Mar 2001 Jeremy Siek +// Moved test of indirect iterator into its own file. It to +// to be in iterator_adaptor_test.cpp. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct my_iterator_tag : public std::random_access_iterator_tag { }; + +using boost::dummyT; + +typedef std::deque storage; +typedef std::deque pointer_deque; +typedef std::set iterator_set; + +template +struct indirect_iterator_pair_generator +{ + typedef boost::indirect_iterator iterator; + typedef boost::indirect_iterator const_iterator; +}; + +void more_indirect_iterator_tests() +{ +// For some reason all heck breaks loose in the compiler under these conditions. +#if 1// !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || !defined(__STL_DEBUG) + storage store(1000); + std::generate(store.begin(), store.end(), rand); + + pointer_deque ptr_deque; + iterator_set iter_set; + + for (storage::iterator p = store.begin(); p != store.end(); ++p) + { + ptr_deque.push_back(&*p); + iter_set.insert(p); + } + + typedef indirect_iterator_pair_generator IndirectDeque; + + IndirectDeque::iterator db(ptr_deque.begin()); + IndirectDeque::iterator de(ptr_deque.end()); + assert(static_cast(de - db) == store.size()); + assert(db + store.size() == de); + IndirectDeque::const_iterator dci(db); + assert(db == dci); + assert(dci == db); + assert(dci != de); + assert(dci < de); + assert(dci <= de); + assert(de >= dci); + assert(de > dci); + dci = de; + assert(dci == de); + + boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin())); + + *db = 999; + assert(store.front() == 999); + + // Borland C++ is getting very confused about the typedef's here + + typedef boost::indirect_iterator indirect_set_iterator; + + typedef boost::indirect_iterator const_indirect_set_iterator; + + indirect_set_iterator sb(iter_set.begin()); + indirect_set_iterator se(iter_set.end()); + const_indirect_set_iterator sci(iter_set.begin()); + assert(sci == sb); + assert(sci != se); + sci = se; + assert(sci == se); + + *boost::prior(se) = 888; + assert(store.back() == 888); + assert(std::equal(sb, se, store.begin())); + + boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]); + assert(std::equal(db, de, store.begin())); + +#endif +} + +int +main() +{ + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + + // Test indirect_iterator_generator + { + dummyT* ptr[N]; + for (int k = 0; k < N; ++k) + ptr[k] = array + k; + + typedef boost::indirect_iterator indirect_iterator; + + typedef boost::indirect_iterator const_indirect_iterator; + + indirect_iterator i(ptr); + boost::random_access_iterator_test(i, N, array); + +#if 0 // BOOST_NO_STD_ITERATOR_TRAITS + boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array); +#endif + + // check operator-> + assert((*i).m_x == i->foo()); + + const_indirect_iterator j(ptr); + boost::random_access_iterator_test(j, N, array); + + +#if 0 // BOOST_NO_STD_ITERATOR_TRAITS + dummyT*const* const_ptr = ptr; + boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array); +#endif + boost::const_nonconst_iterator_test(i, ++j); + + more_indirect_iterator_tests(); + } + std::cout << "test successful " << std::endl; + return 0; +}